001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.page.document.psml;
018:
019: import java.util.Collection;
020: import java.util.List;
021: import java.util.Locale;
022:
023: import org.apache.jetspeed.JetspeedActions;
024: import org.apache.jetspeed.om.common.GenericMetadata;
025: import org.apache.jetspeed.om.common.SecurityConstraints;
026: import org.apache.jetspeed.om.page.PageMetadataImpl;
027: import org.apache.jetspeed.om.page.PageSecurity;
028: import org.apache.jetspeed.om.page.psml.AbstractBaseElement;
029: import org.apache.jetspeed.om.page.psml.SecurityConstraintsImpl;
030: import org.apache.jetspeed.page.document.Node;
031:
032: /**
033: * <p>
034: * AbstractNode
035: * </p>
036: * <p>
037: *
038: * </p>
039: *
040: * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
041: * @version $Id: AbstractNode.java 551606 2007-06-28 16:07:53Z taylor $
042: *
043: */
044: public abstract class AbstractNode extends AbstractBaseElement
045: implements Node {
046: private PageMetadataImpl metadata;
047: private Node parent;
048: private String path;
049: private String url;
050: private boolean hidden = false;
051: private String profiledPath;
052: private boolean dirty = false;
053:
054: public AbstractNode() {
055: }
056:
057: /**
058: * getMetadata - get/construct metadata
059: *
060: * @return metadata
061: */
062: public GenericMetadata getMetadata() {
063: return getPageMetadata();
064: }
065:
066: /**
067: * setMetadata - set metadata fields
068: *
069: * @param metadata metadata
070: */
071: public void setMetadata(GenericMetadata metadata) {
072: getPageMetadata().setFields(metadata.getFields());
073: }
074:
075: /**
076: * getMetadataFields - get metadata fields collection for
077: * marshalling/unmarshalling
078: *
079: * @return metadata fields collection
080: */
081: public Collection getMetadataFields() {
082: // return metadata fields collection that
083: // may in fact be side effected on unmarshall
084: return getPageMetadata().getFields();
085: }
086:
087: /**
088: * setMetadataFields - set metadata fields collection
089: *
090: * @param metadataFields metadata fields collection
091: */
092: public void setMetadataFields(Collection metadataFields) {
093: // set metadata fields collection that
094: // may in fact be side effected after
095: // invocation on unmarshall
096: getPageMetadata().setFields(metadataFields);
097: }
098:
099: /**
100: * getPageMetadata - get/construct page metadata instance
101: *
102: * @return metadata instance
103: */
104: private PageMetadataImpl getPageMetadata() {
105: if (metadata == null) {
106: metadata = new PageMetadataImpl();
107: }
108: return metadata;
109: }
110:
111: /**
112: * <p>
113: * getTitle
114: * </p>
115: *
116: * @see org.apache.jetspeed.page.document.Node#getTitle(java.util.Locale)
117: * @param locale
118: * @return title in specified locale
119: */
120: public String getTitle(Locale locale) {
121: // get title from metadata or use default title
122: String title = getPageMetadata().getText("title", locale);
123: if (title == null) {
124: title = getTitle();
125: }
126: return title;
127: }
128:
129: /**
130: * <p>
131: * getShortTitle
132: * </p>
133: *
134: * @see org.apache.jetspeed.page.document.Node#getShortTitle(java.util.Locale)
135: * @param locale
136: * @return short title in specified locale
137: */
138: public String getShortTitle(Locale locale) {
139: // get short title from metadata or use title from metadata,
140: // default short title, or default title
141: String shortTitle = getPageMetadata().getText("short-title",
142: locale);
143: if (shortTitle == null) {
144: shortTitle = getPageMetadata().getText("title", locale);
145: if (shortTitle == null) {
146: shortTitle = getShortTitle();
147: if (shortTitle == null) {
148: shortTitle = getTitle();
149: }
150: }
151: }
152: return shortTitle;
153: }
154:
155: /**
156: * <p>
157: * getParent
158: * </p>
159: *
160: * @param checkAccess flag
161: * @return parent node
162: */
163: public Node getParent(boolean checkAccess) {
164: AbstractNode parent = (AbstractNode) this .parent;
165:
166: // check access
167: if ((parent != null) && checkAccess) {
168: parent.checkAccess(JetspeedActions.VIEW);
169: }
170: return parent;
171: }
172:
173: /**
174: * <p>
175: * getParent
176: * </p>
177: *
178: * @see org.apache.jetspeed.page.document.Node#getParent()
179: * @return parent node
180: */
181: public Node getParent() {
182: // by default disable access checks since it is assumed
183: // that by accessing this node, access to parent must
184: // also be granted
185: return getParent(false);
186: }
187:
188: /**
189: * <p>
190: * setParent
191: * </p>
192: *
193: * @see org.apache.jetspeed.page.document.Node#setParent(Node)
194: * @param parent
195: */
196: public void setParent(Node parent) {
197: this .parent = parent;
198: }
199:
200: /**
201: * <p>
202: * getName
203: * </p>
204: *
205: * @see org.apache.jetspeed.page.document.Node#getName()
206: * @return Name
207: */
208: public String getName() {
209: // simply strip path to determine name
210: String name = getPath();
211: if ((name != null) && !name.equals(PATH_SEPARATOR)) {
212: if (name.endsWith(PATH_SEPARATOR)) {
213: name = name.substring(0, name.length() - 1);
214: }
215: name = name.substring(name.lastIndexOf(PATH_SEPARATOR) + 1);
216: }
217: return name;
218: }
219:
220: /**
221: * getTitleName - get name for use as default titles
222: *
223: * @return title name
224: */
225: public String getTitleName() {
226: String titleName = getName();
227: if (titleName != null) {
228: // transform file system name to title
229: if (titleName.endsWith(getType())) {
230: titleName = titleName.substring(0, titleName.length()
231: - getType().length());
232: } else if (titleName.equals(PATH_SEPARATOR)) {
233: titleName = "top";
234: }
235: titleName = titleName.replace('_', ' ');
236: titleName = titleName.replace('-', ' ');
237: int wordIndex = -1;
238: do {
239: if (!Character.isTitleCase(titleName
240: .charAt(wordIndex + 1))) {
241: StringBuffer makeTitle = new StringBuffer();
242: makeTitle.append(titleName.substring(0,
243: wordIndex + 1));
244: makeTitle.append(Character.toTitleCase(titleName
245: .charAt(wordIndex + 1)));
246: makeTitle
247: .append(titleName.substring(wordIndex + 2));
248: titleName = makeTitle.toString();
249: }
250: wordIndex = titleName.indexOf(' ', wordIndex + 1);
251: } while (wordIndex != -1);
252: }
253: return titleName;
254: }
255:
256: /**
257: * @return Returns the path.
258: */
259: public String getPath() {
260: return path;
261: }
262:
263: /**
264: * <p>
265: * setPath
266: * </p>
267: *
268: * @param path The path to set.
269: */
270: public void setPath(String path) {
271: // PSML id is always kept in sync with path, despite how the
272: // id may be loaded from the persistent store
273: this .path = path;
274: setId(path);
275: }
276:
277: /**
278: * <p>
279: * getUrl
280: * </p>
281: * Same as invoking <code>Node.getPath()</code> unless url explicitly set.
282: *
283: * @see org.apache.jetspeed.page.document.Node#getUrl()
284: * @return url as string
285: */
286: public String getUrl() {
287: if (url != null) {
288: return url;
289: }
290: return getPath();
291: }
292:
293: /**
294: * <p>
295: * setUrl
296: * </p>
297: *
298: * @param url The url to set.
299: */
300: public void setUrl(String url) {
301: this .url = url;
302: }
303:
304: /**
305: * <p>
306: * isHidden
307: * </p>
308: *
309: * @see org.apache.jetspeed.page.document.Node#isHidden()
310: * @return hidden
311: */
312: public boolean isHidden() {
313: return hidden;
314: }
315:
316: /**
317: * @param hidden The hidden to set.
318: */
319: public void setHidden(boolean hidden) {
320: this .hidden = hidden;
321: }
322:
323: /**
324: * @return Returns the profiled path.
325: */
326: public String getProfiledPath() {
327: return profiledPath;
328: }
329:
330: /**
331: * @param profiledPath The profiled path to set.
332: */
333: public void setProfiledPath(String profiledPath) {
334: this .profiledPath = profiledPath;
335: }
336:
337: /**
338: * getEffectivePageSecurity
339: *
340: * @see org.apache.jetspeed.om.page.psml.AbstractBaseElement#getEffectivePageSecurity()
341: */
342: public PageSecurity getEffectivePageSecurity() {
343: // by default, delegate to parent node implementation
344: if (parent != null) {
345: return ((AbstractNode) parent).getEffectivePageSecurity();
346: }
347: return null;
348: }
349:
350: /**
351: * <p>
352: * checkConstraints
353: * </p>
354: *
355: * @param actions
356: * @param userPrincipals
357: * @param rolePrincipals
358: * @param groupPrincipals
359: * @param checkNodeOnly
360: * @param checkParentsOnly
361: * @throws SecurityException
362: */
363: public void checkConstraints(List actions, List userPrincipals,
364: List rolePrincipals, List groupPrincipals,
365: boolean checkNodeOnly, boolean checkParentsOnly)
366: throws SecurityException {
367: // check constraints in node hierarchy
368: if (checkNodeOnly) {
369: // check node constraints if available; otherwise,
370: // recursively check parent constraints until
371: // default constraints for node are checked
372: SecurityConstraints constraints = getSecurityConstraints();
373: if ((constraints != null) && !constraints.isEmpty()) {
374: ((SecurityConstraintsImpl) constraints)
375: .checkConstraints(actions, userPrincipals,
376: rolePrincipals, groupPrincipals,
377: getEffectivePageSecurity());
378: } else if (parent != null) {
379: ((AbstractNode) parent).checkConstraints(actions,
380: userPrincipals, rolePrincipals,
381: groupPrincipals, checkNodeOnly, false);
382: }
383: } else {
384: // check node constraints if available and not
385: // to be skipped due to explicity granted access
386: if (!checkParentsOnly) {
387: SecurityConstraints constraints = getSecurityConstraints();
388: if ((constraints != null) && !constraints.isEmpty()) {
389: ((SecurityConstraintsImpl) constraints)
390: .checkConstraints(actions, userPrincipals,
391: rolePrincipals, groupPrincipals,
392: getEffectivePageSecurity());
393: }
394: }
395:
396: // recursively check all parent constraints in hierarchy
397: if (parent != null) {
398: ((AbstractNode) parent).checkConstraints(actions,
399: userPrincipals, rolePrincipals,
400: groupPrincipals, false, false);
401: }
402: }
403: }
404:
405: /**
406: * <p>
407: * checkPermissions
408: * </p>
409: *
410: * @param path
411: * @param mask Mask of actions requested
412: * @param checkNodeOnly
413: * @param checkParentsOnly
414: * @throws SecurityException
415: */
416: public void checkPermissions(String path, int mask,
417: boolean checkNodeOnly, boolean checkParentsOnly)
418: throws SecurityException {
419: // check granted node permissions unless the check is
420: // to be skipped due to explicity granted access
421: if (!checkParentsOnly) {
422: super .checkPermissions(path, mask, true, false);
423: }
424:
425: // if not checking node only, recursively check
426: // all parent permissions in hierarchy
427: if (!checkNodeOnly && (parent != null)) {
428: ((AbstractNode) parent)
429: .checkPermissions(mask, false, false);
430: }
431: }
432:
433: /**
434: * <p>
435: * getLogicalPermissionPath
436: * </p>
437: *
438: * @return path used for permissions checks
439: */
440: public String getLogicalPermissionPath() {
441: return profiledPath;
442: }
443:
444: /**
445: * <p>
446: * getPhysicalPermissionPath
447: * </p>
448: *
449: * @return path used for permissions checks
450: */
451: public String getPhysicalPermissionPath() {
452: return path;
453: }
454:
455: /**
456: * unmarshalled - notification that this instance has been
457: * loaded from the persistent store
458: */
459: public void unmarshalled() {
460: // notify super class implementation
461: super .unmarshalled();
462:
463: // force metadata update after unmarshalled since
464: // metadata collection can be side effected by
465: // unmarshalling colection accessors
466: Collection metadataFields = getMetadataFields();
467: if (metadataFields != null) {
468: setMetadataFields(metadataFields);
469: }
470: }
471:
472: public boolean isDirty() {
473: return dirty;
474: }
475:
476: public void setDirty(boolean dirty) {
477: this.dirty = dirty;
478: }
479:
480: }
|