'Framework'에 해당되는 글 84건

  1. 2009.04.30 AL : Permission (1)
  2. 2009.04.30 AL : 현재의 난제들
  3. 2009.04.28 AL : Workspace
  4. 2009.04.26 AL : Property Type Conversion
  5. 2009.04.25 AL : Reading
  6. 2009.04.24 AL : Link
  7. 2009.04.24 AL : Observation
  8. 2009.04.24 AL : Versioning Model
  9. 2009.04.23 AL : Workspace
  10. 2009.04.23 AL : Node
Framework/Another Lore2009. 4. 30. 11:26

Permissions encompass the restrictions imposed by any access control restrictions that may be in effect upon the content of a repository, either implementation specific or JCR-defined

In repositories that support Access Control this will include the restrictions governed by privileges but may also include any additional policy-internal refinements with effects too fine-grained to be exposed through privilege discovery


Permissions are reported through
     boolean Session.hasPermission(String absPath, String actions)

which returns true if this Session has permission to perform all of the specified actions at the specified absPath and returns false otherwise. Similarly, void Session.checkPermission(String absPath, String actions) throws an AccessDeniedException if the this Session does not have permission to perform the specified actions and returns quietly if it does.


The actions parameter is a comma separated list of action strings, of which there are four, defined as follows:

  create: The permission to add a node at absPath.
  update: The permission to set (add or change) a property at absPath.
  delete: The permission to remove an item at absPath.
  read: The permission to retrieve (and read the value of, in the case of a property) an item at absPath.


The permission actions add_node, set_property and remove will only be relevant in a writable repository. In a read-only repository they will always return false. The information returned through these methods only reflects access controlrelated restrictions, not other kinds of restrictions such as node type constraints.

For example, even though hasPermission may indicate that a particular Session may add a property at /A/B/C, the node type of the node at /A/B may prevent the addition of a property called C.

SampleCode

package com.bleujin.lore.core.security;

import com.bleujin.lore.addon.security.Group;
import com.bleujin.lore.addon.security.IResource;
import com.bleujin.lore.addon.security.IUser;
import com.bleujin.lore.addon.security.Member;
import com.bleujin.lore.addon.security.UserAuthority;
import com.bleujin.lore.addon.security.UserAuthority.Range;
import com.bleujin.lore.addon.security.UserAuthority.Type;
import com.bleujin.lore.core.TestCaseParent;
import com.bleujin.lore.core.exception.ALRepositoryException;
import com.bleujin.lore.core.node.Node;

public class TestSecurity extends TestCaseParent {

  private Group adminGroup = new Group("admin");
  private Group normalGroup = new Group("normal");
  private Member bleujin = new Member("bleujin");

  private Node lvl1 = null;
  private Node lvl2 = null;

  private NodeResource lvl1Resource = null;
  private NodeResource lvl2Resource = null;
  private TransientSecurityFilter sf = null;
  private AuthoritySetting setting = AuthoritySetting.createDefault() ;

  public void setUp() throws Exception {
    super.setUp();

    lvl1 = createNode(objectType, "level1");
    lvl2 = createNode(lvl1, objectType, "level2");

    lvl1Resource = new NodeResource(lvl1);
    lvl2Resource = new NodeResource(lvl2);

    sf = new TransientSecurityFilter(setting);
  }

  private boolean isAllowed(IResource resource, IUser user, NodeAction actionthrows ALRepositoryException{
    return sf.isAllowed(resource, user, action;
  }
  
  public void testResourceInherit() throws Exception {
    setting.add(new UserAuthority(lvl1Resource, bleujin, setting.readAuthority(), Range.ONLY_THIS_RESOURCE, Type.GRANT));

    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    // test include Sub
    setting.add(new UserAuthority(lvl1Resource, bleujin, setting.readAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.GRANT))// inherit..
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    UserAuthority lvl2Revoke = new UserAuthority(lvl2Resource, bleujin, setting.readAuthority(), Range.ONLY_THIS_RESOURCE, Type.REVOKE);
    setting.add(lvl2Revoke);
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

  }

  public void testEqual() throws Exception {
    setting.add(new UserAuthority(lvl2Resource, bleujin, setting.readAuthority(), Range.ONLY_THIS_RESOURCE, Type.GRANT));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    setting.remove(new UserAuthority(lvl2Resource, bleujin, setting.readAuthority(), Range.ONLY_THIS_RESOURCE, Type.REVOKE));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));
  }

  public void testAuthorityInherit() throws Exception {
    setting.add(new UserAuthority(lvl1Resource, bleujin, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.GRANT));
    bleujin = new Member("bleujin");
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));

    setting.add(new UserAuthority(lvl2Resource, bleujin, setting.readAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.REVOKE));
    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("write")));
  }

  public void testUserInherit() throws Exception {
    setting.add(new UserAuthority(lvl1Resource, adminGroup, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.GRANT));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl1Resource, bleujin, NodeAction.create("manager")));
    assertEquals(false, isAllowed(lvl1Resource, bleujin, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));

    bleujin = new Member("bleujin");
    bleujin.partIn(adminGroup);

    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));
  }

  public void testMultiGroup() throws Exception {
    // adminGroup <- bleujin
    // normalGroup <- bleujin
    setting.add(new UserAuthority(lvl1Resource, adminGroup, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.GRANT));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    bleujin.partIn(adminGroup);
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    setting.add(new UserAuthority(lvl2Resource, normalGroup, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.REVOKE));
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));

    bleujin.partIn(normalGroup);
    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("write")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));

    normalGroup = new Group("normal");
    bleujin.dropOut(normalGroup);
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("write")));
  }

  public void testGroup() throws Exception {
    // adminGroup <- normarGroup <- bleujin
    setting.add(new UserAuthority(lvl1Resource, adminGroup, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.GRANT));
    setting.add(new UserAuthority(lvl2Resource, normalGroup, setting.managerAuthority(), Range.INCLUDE_SUB_RESOURCE, Type.REVOKE));
    assertEquals(true, isAllowed(lvl1Resource, adminGroup, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    bleujin.partIn(adminGroup);
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    normalGroup.partIn(adminGroup);
    assertEquals(true, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));

    bleujin.partIn(normalGroup);
    assertEquals(true, isAllowed(lvl1Resource, bleujin, NodeAction.create("read")));
    assertEquals(false, isAllowed(lvl2Resource, bleujin, NodeAction.create("read")));
  }
}


'Framework > Another Lore' 카테고리의 다른 글

read & write  (0) 2009.06.25
최근에 책을 읽다가..  (0) 2009.06.11
AL : Permission  (1) 2009.04.30
AL : 현재의 난제들  (0) 2009.04.30
AL : Workspace  (0) 2009.04.28
AL : Property Type Conversion  (0) 2009.04.26
Posted by bleujin

댓글을 달아 주세요

  1. Le maire de Bordeaux et ministre de la Défense Alain Juppé a estimé sur son blog qu'il fallait "abandonner purement et simplement" les 35H comme "une vieille idée du siècle dernier, http://www.timberlandbaratas.com Hombre Timberland, en complet décalage avec la réalité économique d'aujourd'hui", http://www.timberlandbaratas.com zapatos timberland. Politique Amara nommée inspectrice générale des Affaires sociales Politique Hippodrome de Compiègne: décision d'un commun accord Agriculture/Bercy (Matignon)Related articles:


    http://blog.yagom.net/415 En attendant l'annonce d'un second épisode

    http://dkfj3423.tistory.com/?page=3 Au lendemain du décès d'un disc-jockey de 33 ans battu à mort au Blanc-Mesnil (Seine-Saint-Denis)

    2012.12.25 13:47 [ ADDR : EDIT/ DEL : REPLY ]

Framework/Another Lore2009. 4. 30. 10:48


Wokrspace의 Security의 문제
현재 AL Workspace의 보안 Role 모델은 Window의 탐색기로 시작했다. 
각각의 컴퓨터의 탐색기는 별도의 Root를 가지고 모든 파일을 TreePath로 접근할수 있다.

Storage가 물리적인 의미인 반면에 Workspace는 물리적이 아니라 논리적인 의미이다.

A컴퓨터를 GroupA와 GroupB사용자가 하나의 Storage로 각각 다른 Workspace를 사용할때(하나의 Storage를 2개 이상의 Workspace로 사용할때) GroupA와 GroupB는 별도의 TreePath를 가지며 각각의 Workspace에서 TreePath는 유니크하다. 여기까지는 문제가 없다.

단 Node의 UUID로 접근할때 이를 허용해야 하는가의 문제이다. 이를 허용하면 Workspace가 물리적으로 나뉘어 있을때도 접근을 허용해야 하는 문제가 있다. 허용하지 않으려면 매번 WorkspaceName을 검사해야 한다. 이 문제는 일반적인 규악이 없고 Workspace간의 SharableNode의 문제와 얽히기 때문에 머리에서 쥐가 난다.


프로그램에는 How의 코딩의 문제를 벗어나게 되면 일반적으로 2가지 문제가 있는데 하나는 다른 이해 관계자와 커뮤니케이션의 문제이고 두번째는 무엇(What)을 해야 하는가이다. 이런 종류는 방법이 없는게 문제가 아니라 방법이 너무 많아서 어느게 가장 좋은 방법인가를 지금은 알지 못한다에 문제가 있다.


이 문제를 bleujin식 난제 네이밍관례에 따라 "아들을 아들이라 부르지 못하고.." 문제로 정의하였다.




AL은 국제화
AL은 OR Mapping이 아닌 Repository에 가깝기 때문에 UTF인코딩을 넘어서는 국제화를 지원해야 한다.

이를테면 우리나라는 GMT+9의 Timezone에 있다. 날짜는 절대시간으로서의 인식과 상대시간으로의 인식이 있는데 오스트리아의 오늘 일몰 시간은 오후 07:13분입니다 라고 할때는 절대시간으로서 저장해야 하고 오스트리아의 오후 7시 13분이 우리나라 시간으로 몇시지? 라고 생각하면 상대시간으로 저장해야 한다.

그러나 시간은 말하지 않기 때문에 사용자가 Property에 날짜값을 설정했을때 어느 시간으로 저장해야 하는가에 대한 문제가 있다. 이를테면 호주에서 4월 30일 오후 9시 20분이라고 입력한 것과 우리나라에서 4월 30일 오후 9시 20분이라고 입력한것은 전혀 다르다.

그래서 Calendar Property는 UTC로 저장한다. 그런데 사용자의 접속시간 등 다른 시간들의 표현에 문제가 있다. 난 오전 10시에 로그인했는데 오전 1시에 접속한 걸로 나오면 아마 프로그래밍 버그를 의심할 것이다.

이런 날짜의 문제뿐 아니라 이전 국제화 글에서 지적한 바와 같이 숫자의 표현 등에도 난제는 많다. (통화는 PropertyType에 없다는 것이 좀 위안이 된다. -ㅅ-)  이 것을 "시간의 침묵" 이라고 부르기로 했다. -ㅅ-

'Framework > Another Lore' 카테고리의 다른 글

최근에 책을 읽다가..  (0) 2009.06.11
AL : Permission  (1) 2009.04.30
AL : 현재의 난제들  (0) 2009.04.30
AL : Workspace  (0) 2009.04.28
AL : Property Type Conversion  (0) 2009.04.26
AL : Reading  (0) 2009.04.25
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 28. 11:59


A repository may support workspace management. A repository that supports this feature must the semantics of multiple workspaces  and support cross-workspace operations (copying across Workspaces and cloning and updating node, share node)

AL은 Worksapce에서 좀 다른 기능을 가지고 있다.

AL은 1개 이상의 Workspae로 구성되어 있고 AnotherLore.login(new Credential("bleujin"), "otherWorkspaceName") ; 로 통해 default가 아닌 다른 Worksapce에 접속할 수 있다.

이를테면 이런 경우를 생각하면 된다. AL을 이용하여 인사관리 시스템을 만들었다. 이제 재고관리 프로그램을 만들어야 할때 또 다른 AL을 설치해야 할까?


또 다른 AL이 필요치는 않다. 다만 새로운 Workspace를 정의해 두고 재고관리 프로그램은 이 newWorkspace를 사용하면 된다. 

 <global-store> 
  <reference-storage>default-dc</reference-storage>
 </global-store>


 <workspaces>
  <workspace name="default_workspace" default="true">
   <default-locale>ko</default-locale>
   <reference-storage>default-dc</reference-storage>
  </workspace>

  <workspace name="other_workspace">
   <default-locale>en</default-locale>
   <reference-storage>default-dc</reference-storage>
  </workspace>

  <workspace name="other2_workspace">
   <default-locale>en</default-locale>
   <reference-storage>default-mm</reference-storage>
  </workspace>

 </workspaces>
 
 
 <storage id="default-mm" type="memory">
 </storage>

 <storage id="default-dc" type="db.oracle">

 <database-controller>
  <controller-name>framework default database service</controller-name>
  <database-manager>
   <!-- Development server2 ,novision -->

   <description>Oracle database manager.</description>
   <configured-object>
    <class-name>com.bleujin.framework.db.manager.Oracle9iCacheDBManager</class-name>
    <constructor>
     <constructor-param>
      <description>jdbcURL</description>
      <type>java.lang.String</type>
      <value>jdbc:oracle:thin:@novision:1521:bleujin</value>
     </constructor-param>
     <constructor-param>
      <description>userId</description>
      <type>java.lang.String</type>
      <value>al</value>
     </constructor-param>
     <constructor-param>
      <description>password</description>
      <type>java.lang.String</type>
      <value>redf</value>
     </constructor-param>
     <constructor-param>
      <description>connectionLimit</description>
      <type>int</type>
      <value>10</value>
     </constructor-param>
    </constructor>
   </configured-object>
   
  </database-manager>
  <test-query>select 1</test-query>

 </database-controller>
 </storage>
 
위와 같이 설정되 있을 경우 AL은 1개의 GlobalStorage와 3개의 WorkspaceStorage를 가진다.
GlobalStorage는 주로 NodeType과 Sequecne등의 Global 객체 정보를 가지고 있으며 개개의 Workspace는 개별적인 Tree 형태의 Node 구조를 가지고 있다.

특징적인 점은 other_workspace와 other_workspace는 같은 DB를 참조하고 있다. Workspace는 Storage형태가 메모리이든(물론 이경우 매번 리셋된다.) DB이든 상관하지 않으며 다른 DB 종류일수도 있고 같은 DB이지만 Schema만 다를 수 있고 심지어는 같은 DB의 같은 Table에 여러개의 workspace 정보를 관리할 수도 있다.

이런 구조를 택한 이유는 Workspace로 관리하고자 하는 Node의 양이 상황에 따라 다르기 때문이다. 이를테면 A Workspace가 전체 노드의 50%이상이고 나머지 50% 이하를 9개의 Workspace가 관리한다면 A Workspace만 별도의 DB로 관리하고 나머지 9개를 하나의 Storage로 공유하여 사용할 수 있다.

AnotherLore.logn(Credential)로 접속을 하면 default=true인 Default Worksapce로 접속하고 일반적으로는 AnotherLore.login(Credintial, workspaceName)으로 별도의 Session을 할당받는다.

기본적으로는 A workspace로 login해서 얻은 NodeA는
B Workspace의 NodeB를 Node.getIdentifier로 언제든 참조할 수 있지만 각각의 Workspace는 개별적인 SecurityFilter를 관리하기 때문에 특정 ShareNode만 노출시킬 수도 있다.









'Framework > Another Lore' 카테고리의 다른 글

AL : Permission  (1) 2009.04.30
AL : 현재의 난제들  (0) 2009.04.30
AL : Workspace  (0) 2009.04.28
AL : Property Type Conversion  (0) 2009.04.26
AL : Reading  (0) 2009.04.25
AL : Link  (0) 2009.04.24
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 26. 06:54

When the value of a property is read or written using a type different from that declared for the property, the repository attempts a type conversion according to the following rules. Note that even in cases where the type conversion is
defined in terms of standard JDK type conversion method, failure of conversion must only ever cause a ValueFormatException to be thrown and never any exception defined in the JDK API.



From STRING To

INPUTSTREAM: The string is encoded using UTF-8.
DATE: If the string is in the format(yyyyMMdd hh24miss) From DATE To, it is converted directly,
     otherwise a ValueFormatException is thrown.
DOUBLE: The string is converted using java.lang.Double.valueOf(String).
DECIMAL: The string is converted using the constructor java.math.BigDecimal(String).
LONG: The string is converted using java.lang.Long.valueOf(String).
BOOLEAN: The string is converted using java.lang.Boolean.valueOf(String).
OBJECT : The string(String)


From BINARY To

STRING: return binary.toXML().toString()
OBJECT : return binary (BinaryPropertyValue)
All Others: A ValueFormatException is thrown.



From DATE To

STRING: The date is converted to the following format:
   yyyyMMdd hh24miss(gregorian
INPUTSTREAM: The date is converted to a string, and this string is encoded in UTF-8.
DOUBLE: The date is converted to the number of milliseconds
     since 00:00 (UTC) 1 January 1970 (1970-01-01T00:00:00.000Z).
     If this number is out-of-range for a double, a ValueFormatException is thrown.
DECIMAL: The date is converted to the number of milliseconds
      since 00:00 (UTC) 1 January 1970(1970-01-01T00:00:00.000Z).
LONG: The date is converted to the number of milliseconds
      since 00:00 (UTC) 1 January 1970 (1970-01-01T00:00:00.000Z). 
      If this number is out-of-range for a long, a ValueFormatException is thrown.
OBJECT : The date(Calendar of Gregorian)
All Others: A ValueFormatException is thrown.


From DOUBLE To

STRING: The double is converted using java.lang.Double.toString().
INPUTSTREAM: The double is converted to a string, and this string is encoded in UTF-8.
DECIMAL: The double is converted using the constructor java.math.BigDecimal(double).
DATE: The double is coerced to a long using standard Java type coercion
      and interpreted as the number of milliseconds since 00:00 (UTC) 1 January 1970(1970-01-01T00:00:00.000Z).
      If the resulting value is out of range for a date, a ValueFormatException is thrown.
LONG: Standard Java type coercion is used.
OBJECT : The double (Double)
All Others: A ValueFormatException is thrown.


From DECIMAL To

STRING: The decimal is converted using java.math.BigDecimal.toString().
INPUTSTREAM: The decimal is converted to a string, and this string is encoded in UTF-8.
DOUBLE: The decimal is converted using java.math.BigDecimal.doubleValue().
DATE: The decimal is converted to a long and interpreted as the number of milliseconds
      since 00:00 (UTC) 1 January 1970 (1970-01-01T00:00:00.000Z).
      If the resulting value is out of range for a date, a ValueFormatException is thrown.
LONG: The decimal is converted using java.math.BigDecimal.longValue().
OBJECT : The decimal(BigDecimal)
All Others: A ValueFormatException is thrown.


From LONG To

STRING: The long is converted using java.lang.Long.toString().
INPUTSTREAM: The long is converted to a string, and this string is encoded in UTF-8.
DECIMAL: The double is converted using the method java.math.BigDecimal.valueOf(long).
DATE: The long is interpreted as the number of milliseconds
     since 00:00 (UTC) 1 January 1970 (1970-01-01T00:00:00.000Z).
     If the resulting value is out of range for a date, a ValueFormatException is thrown.
DOUBLE: Standard Java type coercion is used.
OBJECT : The long(Long)
All Others: A ValueFormatException is thrown.


From BOOLEAN To

STRING: The boolean is converted using java.lang.Boolean.toString().
INPUTSTREAM: The boolean is converted to a string, and this string is encoded in UTF-8.
OBJECT : The boolean(Boolean)
All Others: A ValueFormatException is thrown.



From NAME

STRING: The name is converted to qualified name(IDString)
INPUTSTREAM: The name is converted to a string, and then encoded using UTF-8.
OBJECT : The name(IDString)
All Others: A ValueFormatException is thrown.


From PATH

STRING: The name is converted to qualified name(IDString)
INPUTSTREAM: The name is converted to a string, and then encoded using UTF-8.
OBJECT : The node of path(Node)
All Others: A ValueFormatException is thrown.


From REFERENCE

STRING: The reference is converted to string
INPUTSTREAM: The name is converted to a string, and then encoded using UTF-8.
OBJECT : The node of identifier(Node)
All Others: A ValueFormatException is thrown.



From TEXT

STRING: The text is converted to string
INPUTSTREAM: The text is converted to a string, and then encoded using UTF-8.
OBJECT : The text is converted to stringBuffer
All Others: A ValueFormatException is thrown.



From VERTUAL_TEXT

STRING: The text is converted to string
INPUTSTREAM: The text is converted to a string, and then encoded using UTF-8.
OBJECT : The text is converted to translated string(translate template)
All Others: A ValueFormatException is thrown.





'Framework > Another Lore' 카테고리의 다른 글

AL : 현재의 난제들  (0) 2009.04.30
AL : Workspace  (0) 2009.04.28
AL : Property Type Conversion  (0) 2009.04.26
AL : Reading  (0) 2009.04.25
AL : Link  (0) 2009.04.24
AL : Observation  (0) 2009.04.24
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 25. 05:21

There are three types of read access which a session may have with respect to a particular node(or property), depending on that session's permissions: direct access, traversal access and search access.


Direct Access

Direct access to an item means being able to retrieve it by absolute and relative path and, in the case of nodes, by identifier. Let p(x) return the normalized absolute path of item x,  id(x) return the identifier of node x.

For any session S and node N, the statements below must be either all true or all false. If they are all true then S has direct access to N, if they are all false then S does not have direct access to N:

- S.getNodeByPath(p(N)) returns N.
- S.getNodeByUUID(id(x)) return N.
- S.existByPath(p(N)) returns true.
- If N is the root node of the workspace then S.getRootNode() returns N.

For any node N and property P, the statements below must be either all true or all false. p(P) eturn the identifier of property P. If they are all true then N has direct access to P, if they are all false then N does not have direct access to P:

- N.getProperty(p(P)) returns P.
- N.hasProperties(p(P)) return true.
- N.getString(p(P)) return P.getString()

Traversal Access

Traversal access to an node N means that it is returned when iterating over the link of a node.

For any given session S and node N, the statements below must be either both true or both false. If they are both true then S has traversal access to N, if they are both false then S does not have traversal access to N:

- S has access to M where M is the parent of N, and N appears among the node in the iterator returned by either M.getChildNode(int maxDepth) or  M.getChildNode() or M.getChildNode(Page page) or getNodes(LinkType.Child, Page.ALL)
- If N is the parent node of a node M then M.getParent() returns N.
- If N has property thern Node.hasProperties() returns true.
- If N is the member node of a node M, and N apperas among the node in the iterator returned by either M.getMemberNode(Page.ALL) or getNodes(LinkType.Member, Page.ALL)
- If N has link of a node M, and N apperas among the node in the iterator<Link> returned by either M.getLinks(Page.ALL) or M.getLinks(linkType, page). Link consist of fromNode and toNode with linkType

Export
Exporting a subgraph within a workspace can be done with
Exporter.exp()


Search Access

Search a subgraph within a workspace can be done with
Node.searchNode(String searchText)
currently the search engine is Lucene

Effect of Access Denial on Read

If a repository restricts the read access of a session, then the nodes and properties to which that session does not have read access must appear not to exist. For example, the iterator returned on N.getNodes will not include subnodes of N to which the session in question does not have read access. In other words, lack of read access to an item blocks access to both information about the content of that item and information about the existence of that item.

Node Information
This method provides access to the current Session.
    Session node.getSession()
These methods provide information about the location of an node within the workspace hierarchy:
    String node.getPath()
returns the name of the node
    String node.getName()
returns the ancestor of the node that is at the specified depth below the root node.
    Node node.getParent()
returns the name of the node
    String node.getExplain()
returns the more information of the node
    NodeBean node.getBean()
This method is used to determine the repository-level semantic identity of two node.
    boolean node.isSame(Node n2) or boolean node.isSameVersion(Node n2)
The method returns the identifier of a node.
    String Node.getIdentifier()

Iterators

Methods that return a set of Node or Property objects do so using a GenericIterator, subclasses of Iterator.


Reading Properties

The generic value getter for single value properties is
    Value Property.getValue().
returns one of the constants of Property.Type indicating the property type of the Value.
    Property.Type Value.getType()
The length of a value in a single-value property. is returned by
    long Property.getLength()

Property Type Conversion
When the value of a property is read or written using a type different from that declared for the property, the repository attempts a type conversion according to the [not defined] rules. Note that even in cases where the type conversion is
defined in terms of standard JDK type conversion method, failure of conversion must only ever cause a  ValueFormatException to be thrown and never any exception defined in the JDK API.

Namespace Mapping


'Framework > Another Lore' 카테고리의 다른 글

AL : Workspace  (0) 2009.04.28
AL : Property Type Conversion  (0) 2009.04.26
AL : Reading  (0) 2009.04.25
AL : Link  (0) 2009.04.24
AL : Observation  (0) 2009.04.24
AL : Versioning Model  (0) 2009.04.24
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 24. 09:45


Link는 다른 ORMapping이나 JSR283 API에는 나오지 않는 좀 독특한 API이다.

Link는 Node와 Node의 관계이다. Node는
   Node session.createNode(Node parent, NodeType nodetype, String name)
parentNode를 지정하고 create되는데(맨 처음 만들게 되는 root 노드는 NO_PARENTNODE 라는 Node를 ParentNode로 설정한다.) 이때 parentNode와 createdNode 사이에는 자동적으로 Parent-Child Link가 생성된다.

이 자동적으로 생성된 Link를 통해
  Iterator<Node> Node.getChildNode(Page page) API가 동작한다.

그리고 Link는 또한 User가 수동적으로 create시킬수 있다. 가장 대표적인 경우가 MemberType인데

Node boardNode = createNode(root, boardType, "general_board")
Node arcileNode = createNode(boardNode, articleType, sequence.nextVal("board");
articleNode.setSubject("제목") ;
articleNode.setContent("내용") ;

와 같은 코드를 통해 게시판을 구현한다고 했을때.

boardNode와 articleNode는 parent-child 관계이다. 그러나 parent-child 관계는 orderable 하지 않기 때문에 순서가 보장되어야 하는 게시판에는 적당하지 않다.

그럴경우
boardNode.addLink(articleNode, new LinkType("belongTo"), Position.After) 와 같이 명시적으로 새로운 관계를 지정할 수 있다. boardNode는 articleNode와 belongTo 관계를 가지며 관계의 맨끝에 넣으라는 API이다. 그러나 일반적으로 관계는 targNode의 nodeType을 제한하지 않는다. 그래서  Iterator<Node> parentNode.getNodes(new LinkType("belongTo")) 라고 했을때 모두 articleTtype이 나올것이라고 확신할수 없다.

그러나 이런경우라면 굳이 새로운 linkType을 만들 필요는 없다. 이미 이러한 역할을 하는 관계가 있는데 memberType이다.
boardNodeType.setMemberType(articleNodeType) 이라고 지정하면 boardNodeType의 instance인 boardNode는 articleNodeType 혹은 articleNodeType을 상속받은 Node만 member로 지정할 수 있다.

memberLinkType은 order를 지정할 수 있고
   boardNode.getMemberNode(Page page) 와 같이 억세스 할 수 있다.

이미 정의된 parent-child 관계와 member 관계 말고도 원할 경우 어떠한 Link 관계도 맺을 수 있다. 이를테면 boardNode는 특정 articleNode와 mostPopular 관계를 맺어 이를 반복해서 노출시킬 수 있다. 또는 특정 Node끼리 same link를 맺을 수도 있다.

Link의 존재로 인해 Node들을 더 유연하게 참조할 수 있게 된다.

Direction
Link는 FromNode->ToNode의 단방향이다.


[Example Code]

  Node r1 = createNode(root, robotType, "1") ;
  Node r2 = createNode(root, robotType, "2") ;
  Node r3 = createNode(root, robotType, "3") ;
  Node r4 = createNode(root, robotType, "4") ;
  Node r5 = createNode(root, robotType, "5") ;
  
  robotType.setMemberType(robotType) ;
  r1.addLink(r2, LinkTypeImpl.MEMBER, Position.AFTER) ;
  r1.addLink(r3, LinkTypeImpl.MEMBER, Position.AFTER) ;
  r1.addLink(r4, LinkTypeImpl.MEMBER, Position.AFTER) ;
  r1.addLink(r5, LinkTypeImpl.AGREE, Position.AFTER) ;
  
  session.save() ;
  
  assertEquals(3, r1.getLinks(LinkTypeImpl.MEMBER, Page.ALL).size()) ;

  assertEquals(2, r1.getLinks(LinkTypeImpl.MEMBER, Page.create(2, 1)).size()) ;
  assertEquals(1, r1.getLinks(LinkTypeImpl.MEMBER, Page.create(2, 2)).size()) ;
  assertEquals(0, r1.getLinks(LinkTypeImpl.MEMBER, Page.create(2, 3)).size()) ;

  assertEquals(2, r1.getLinks(Page.create(2, 1)).size()) ;
  assertEquals(2, r1.getLinks(Page.create(2, 2)).size()) ;
  assertEquals(0, r1.getLinks(Page.create(2, 3)).size()) ;


<about Link interface in Node >
 public GenericIterator<Node> getChildNode(int maxDepth) throws RepositoryException ;
 public GenericIterator<Node> getChildNode(Page page) throws RepositoryException;
 public GenericIterator<Node> getChildNode() throws RepositoryException;
 public GenericIterator<Node> getMemberNode(Page page) throws RepositoryException ;
 public GenericIterator<Node> getNodes(LinkType type, Page page) throws RepositoryException;

 public GenericIterator<Link> getLinks(Page page) throws RepositoryException;
 public GenericIterator<Link> getLinks(LinkType linkType, Page page) throws RepositoryException  ;



<interface Link extends IConstant, Publishable>

 public void setMode(Mode mode) ;
 public Mode getMode() ;
 public Node getFrom() throws RepositoryException ;
 public LinkType getLinkType();
 public Node getTo() throws RepositoryException ;
 public String getFromUUID() ;
 public String getToUUID() ;
 public Position getPosition() ;







'Framework > Another Lore' 카테고리의 다른 글

AL : Property Type Conversion  (0) 2009.04.26
AL : Reading  (0) 2009.04.25
AL : Link  (0) 2009.04.24
AL : Observation  (0) 2009.04.24
AL : Versioning Model  (0) 2009.04.24
AL : Workspace  (0) 2009.04.23
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 24. 08:42



A repository may support observation, which enables an application to receive notification of persistent changes to a workspace.

Event Model
A persisted change to a workspace is represented by a set of one or more events. Each event reports a single simple change to the structure of the persistent workspace in terms of an item added, changed or removed. The six
standard event types are:

NODE_CREATED, NODE_REMOVED
PROPERTY_CREATED, PROPERTY_CHANGED
LINK_CREATED, LINK_REMOVED


Scope of Event Reporting


The scope of event reporting is implementation-dependent. An implementation should make a best-effort attempt to report all events, but may exclude events if reporting them would be impractical given implementation or resource limitations. For example, on an import, create or remove of a subgraph containing a large number of items, an implementation may choose to report only events associated with the root node of the affected graph and not those for every subitem in the structure.

Event implement
NodeEvent, PropertyEvent, LinkEvent


Event Information
Each Event is associated with a path, an identifier and an information map, the interpretation of which depend upon the event type.

The event path is retrieved through
  NodeEvent.getNode()
  PropertyEvent.getProperty() ;
  LinkEvent.getLink() ;

User ID
An Event also records the identity of the Session that caused it. String Event.getUserID()
String Event.getUserID()
returns the user ID of the Session, which is the same value that is returned by Session.getUserID()


Event Date

An event also records the time of the change that caused it. This acquired through
long Event.getDate()
The date is represented as a millisecond value that is an offset from the epoch January 1, 1970 00:00:00.000 GMT (Gregorian). The granularity of the returned value is implementation-dependent.


Event Ordering

In both asynchronous and journaled observation the order of events within a bundle and the order of event bundles is not guaranteed to correspond to the order of the operations that produced them.

Observation Manager

Registration of event listeners is done through the ObservationManager object acquired from the Workspace through
ObservationManager Workspace.getObservationManager().


Exceptions

The method EventListener.onEvent does not specify a throws clause. This does not prevent a listener from throwing a RuntimeException, although any listener that does should be considered to be in error.


[Example Code]
  EventStackingListener listener = new EventStackingListener();
  workspace.getObservationManager().addEventListener(listener) ;
  
  Node node = session.createNode(root, newType, "abc") ;
  
  assertEquals(3, listener.getCount())  ;
  
  NodeEvent event = (NodeEvent)listener.popEvent();
  assertEquals(EventType.NODE_CREATED, event.getType()) ;
  assertEquals(node, event.getNode()) ;
  assertEquals(EventType.LINK_CREATED, listener.popEvent().getType()) ;
  assertEquals(EventType.PROPERTY_CREATED, listener.popEvent().getType()) ; // because of default value
  
  node.setProperty(IDString.propId("firstname"), "bleujin") ;
  assertEquals(EventType.PROPERTY_CHANGED, listener.popEvent().getEventType()) ;


<interface Event>
 public EventType getType() 
 public String getUserID() 
 public long getDate()


<interface EventListener>
 public void onEvent(Event event);
 public boolean isDealWith(Event event);

'Framework > Another Lore' 카테고리의 다른 글

AL : Reading  (0) 2009.04.25
AL : Link  (0) 2009.04.24
AL : Observation  (0) 2009.04.24
AL : Versioning Model  (0) 2009.04.24
AL : Workspace  (0) 2009.04.23
AL : Node  (0) 2009.04.23
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 24. 05:28


Versioning enables a user to record the state of a node and its subgraph and restore that state at a later time.


Check-In

When node is checked-in, a new version of that node is created which contains a (typically partial) copy of its subgraph. The part of a node’s subgraph that is to be copied to a version is referred to as its versionable
subgraph and constitutes its versionable state. 
A new version of a versionable node is created using
    Version node.checkIn()
This method require exsting node in repository. Created Node but not Saved Node(only exists in memory) may throw a RepositoryException.


Version History

Once created, a version is stored in a version history
The method
    VersionHistory node.getVersionHistory()


Check-Out

Once checked-in, a node and its versionable subgraph become readonly. To alter a checked-in node or its versionable subgraph, the node must first be checked-out. It can then be changed and checked-in again, creating a new version.
The method
    version.checkOut()


Base Version Reference

Each versionable node has a base version within its version history. When a new version of a node is created, it is placed in that node’s version history as a direct successor of the base version. That version itself then becomes the new base version
The method
    Node versionHistory.getRecentNode()


Version Extends Node
The Version interface extends Node.



<interface Version extends Node, Comparable<Version>>
 public Calendar getCreated();
 public void checkOut() throws RepositoryException;
 public Node getRecentNode()throws RepositoryException;
 public GenericIterator<Property> getProperties() throws RepositoryException;
 public Property getProperty(IDString propId) throws RepositoryException;


<interface VersionHistory extends Publishable, IConstant>
 public GenericIterator<Version> getAllVersions();
 public Version getVersion(int versionIndex);
 public Node getRecentNode();

'Framework > Another Lore' 카테고리의 다른 글

AL : Link  (0) 2009.04.24
AL : Observation  (0) 2009.04.24
AL : Versioning Model  (0) 2009.04.24
AL : Workspace  (0) 2009.04.23
AL : Node  (0) 2009.04.23
AL : Property  (0) 2009.04.23
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 23. 12:26


Workspace

AnotherLore repository is composed of one or more persistent workspaces, each of which is a persistent data store consisting of a directed acyclic graph of items where the edges represent the parent-child relation. Each persistent workspace is identified by a name, unique within the repository, which is a string.

this have ValidChain, ObservationManager, LockManager, IndexDirectory, GlobalStore, LocalStore


Storage

GlobalStore : The node type of a AnotherLore is stored, and Sequence, NamespaceRegistry

LocalStore : The nodes of a workspace form the structure of the stored data while the actual content is stored in the values of the properties.


Sessions

All interaction with the repository occurs through a session. A user receives a session upon connecting to the repository by supplying a set of credentials and the name of a persistent workspace to which the user wishes to connect. The returned session binds the user to the requested persistent workspace with a level of authorization determined by that user's credentials. A session is always bound to exactly one persistent workspace, though a single persistent workspace may be bound to multiple sessions.


User

A user is any agent bound to a session. This may be a human user, an external software process, or anything else that holds and controls the session.

Through a session, the user can access, read and write the nodes and properties of the bound workspace, to the extent allowed by that user's authorization and the capabilities of the repository. Any object acquired, directly, or indirectly through a chain of interceding objects, from a particular session, is said to be within the scope of that session and any method called on such object is also within the scope of the same session.

In the context of discussing a particular object or method call, the session within whose scope that object or method call lies is referred to as the current session, and the workspace to which that session is bound is referred to as the current workspace.


Namespaces

nodetype name is an ordered pair of strings: (N, L)
where N is a AnotherLore namespace and L is a local name in a workspace

namespace is a Universal Resource Identifier. and can access other AnotherLore through namespace URI




'Framework > Another Lore' 카테고리의 다른 글

AL : Observation  (0) 2009.04.24
AL : Versioning Model  (0) 2009.04.24
AL : Workspace  (0) 2009.04.23
AL : Node  (0) 2009.04.23
AL : Property  (0) 2009.04.23
AL : PropertyDefinition  (0) 2009.04.23
Posted by bleujin

댓글을 달아 주세요

Framework/Another Lore2009. 4. 23. 12:12

A node can have zero or more child property while a property cannot have children but can hold zero or more values.

Each workspace contains at least one item, the root node, which, uniquely among the items in a workspace, has no parent node. All other items have at least one parent.

The nodes of a workspace form the structure of the stored data while the actual content is stored in the values of the properties.(LocalStore)


Name
The name of the root node of a workspace is always “/”. Every other item in a workspace has the same name relative to each of its parent nodes. This name's type must be a alphaNumUnderBar except root node

For a given node, no two of its properties can have the same name. However, a node and property may have the same name and, in some cases, two or more nodes may have the same name.

Same-Name Siblings is not supported.


Path

The location of an Node in the workspace graph can be described by the path from the root node to that item, consisting of the name of each interceding node in order from root to target item, much like a file system path. Relative paths can also be used to describe the location of one item with respect to another. in A AnotherLore, path is unique



Identifiers

Every node also has an identifier, which, in some implementations, may be independent of its path and provide a second, more stable, form of address for a node. in all distributed AnotherLore, UUID is unique


Property

Properties can be single valued. The value of a property has a type, which is one of 11 possible types . The supported
property types include standard data types such as strings, numbers and dates, as well as pointers to other items in the same workspace (either via path or identifier), which can be used to define relationships between node structures
that cross-cut the workspace hierarchy.



Node Types


Nodes also have types. The type of a node defines which properties and child nodes that node may (or must) have, and the types of those child items in turn. Node types can be used to define complex storage objects consisting of multiple subnodes and properties, possibly many layers deep.


'Framework > Another Lore' 카테고리의 다른 글

AL : Versioning Model  (0) 2009.04.24
AL : Workspace  (0) 2009.04.23
AL : Node  (0) 2009.04.23
AL : Property  (0) 2009.04.23
AL : PropertyDefinition  (0) 2009.04.23
AL : NodeType  (0) 2009.04.23
Posted by bleujin

댓글을 달아 주세요