001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/metaobj/tags/sakai_2-4-1/metaobj-impl/api-impl/src/java/org/sakaiproject/metaobj/shared/mgt/home/StructuredArtifactHome.java $
003: * $Id: StructuredArtifactHome.java 21321 2007-02-11 08:23:36Z john.ellis@rsmart.com $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.metaobj.shared.mgt.home;
021:
022: import java.io.ByteArrayInputStream;
023: import java.io.ByteArrayOutputStream;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.text.MessageFormat;
027: import java.util.Iterator;
028: import java.util.List;
029:
030: import org.jdom.*;
031: import org.jdom.input.SAXBuilder;
032: import org.jdom.xpath.XPath;
033: import org.jdom.output.Format;
034: import org.jdom.output.XMLOutputter;
035: import org.sakaiproject.component.cover.ComponentManager;
036: import org.sakaiproject.metaobj.shared.mgt.*;
037: import org.sakaiproject.metaobj.shared.model.*;
038: import org.sakaiproject.metaobj.shared.ArtifactFinder;
039: import org.sakaiproject.metaobj.utils.Config;
040: import org.sakaiproject.metaobj.utils.xml.SchemaNode;
041: import org.sakaiproject.metaobj.worksite.intf.WorksiteAware;
042: import org.sakaiproject.metaobj.worksite.mgt.WorksiteManager;
043: import org.sakaiproject.metaobj.registry.FormResourceType;
044: import org.sakaiproject.entity.api.ResourcePropertiesEdit;
045: import org.sakaiproject.entity.api.ResourceProperties;
046: import org.sakaiproject.content.cover.ContentHostingService;
047: import org.sakaiproject.content.api.ContentResourceEdit;
048: import org.sakaiproject.content.api.ContentResource;
049: import org.sakaiproject.exception.*;
050: import org.springframework.beans.BeansException;
051: import org.springframework.context.ApplicationContext;
052: import org.springframework.context.ApplicationContextAware;
053:
054: /**
055: * Created by IntelliJ IDEA.
056: * User: John Ellis
057: * Date: May 17, 2004
058: * Time: 2:52:00 PM
059: * To change this template use File | Settings | File Templates.
060: */
061: public class StructuredArtifactHome extends XmlElementHome implements
062: StructuredArtifactHomeInterface, WorksiteAware,
063: ApplicationContextAware, Comparable, StreamableObjectHome {
064:
065: protected final static org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
066: .getLog(StructuredArtifactHome.class);
067:
068: private boolean modifiable = false;
069: private PresentableObjectHome repositoryHelper;
070: private IdManager idManager;
071: private String siteId;
072: private ArtifactFinder artifactFinder;
073:
074: private static final MessageFormat format = new MessageFormat(
075: "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL={0}/member/viewArtifact.osp?artifactId={1}&artifactType={2}&pid={3}\">");
076:
077: public Artifact store(Artifact object) throws PersistenceException {
078: Id id = object.getId();
079:
080: if (id == null) {
081: return addArtifact(object);
082: } else {
083: return updateArtifact(object);
084: }
085: }
086:
087: protected Artifact updateArtifact(Artifact object)
088: throws PersistenceException {
089: StructuredArtifact artifact = (StructuredArtifact) object;
090: String resourceId = ContentHostingService.resolveUuid(artifact
091: .getId().getValue());
092: try {
093: ContentResourceEdit resourceEdit = ContentHostingService
094: .editResource(resourceId);
095: resourceEdit.setContent(getInfoBytes(object));
096: resourceEdit.getProperties().addProperty(
097: ResourceProperties.PROP_DISPLAY_NAME,
098: object.getDisplayName());
099: ContentHostingService.commitResource(resourceEdit);
100: } catch (PermissionException e) {
101: throw new PersistenceException(e, "Unknown file error",
102: null, null);
103: } catch (IdUnusedException e) {
104: throw new PersistenceException(e, "Unknown file error",
105: null, null);
106: } catch (TypeException e) {
107: throw new PersistenceException(e, "Unknown file error",
108: null, null);
109: } catch (InUseException e) {
110: throw new PersistenceException(e, "Unknown file error",
111: null, null);
112: } catch (ServerOverloadException e) {
113: throw new PersistenceException(e, "Unknown file error",
114: null, null);
115: } catch (OverQuotaException e) {
116: throw new PersistenceException(e, "Over quota", null, null);
117: }
118:
119: return object;
120: }
121:
122: public StructuredArtifact load(ContentResource resource) {
123: try {
124: Agent resourceOwner = getAgentManager().getAgent(
125: resource.getProperties().getProperty(
126: ResourceProperties.PROP_CREATOR));
127: Id resourceId = getIdManager().getId(
128: ContentHostingService.getUuid(resource.getId()));
129:
130: SAXBuilder builder = new SAXBuilder();
131: Document doc = builder.build(resource.streamContent());
132:
133: StructuredArtifact xmlObject = new StructuredArtifact(doc
134: .getRootElement(), getSchema().getChild(
135: getRootNode()));
136:
137: xmlObject.setBaseResource(resource);
138: xmlObject.setId(resourceId);
139: xmlObject.setDisplayName((String) resource.getProperties()
140: .get(
141: resource.getProperties()
142: .getNamePropDisplayName()));
143: xmlObject.setHome(this );
144: xmlObject.setOwner(resourceOwner);
145:
146: return xmlObject;
147: } catch (Exception e) {
148: throw new PersistenceException(e, "", null, null);
149: }
150: }
151:
152: private AgentManager getAgentManager() {
153: return (AgentManager) ComponentManager.get("agentManager");
154: }
155:
156: public Artifact load(Id id) throws PersistenceException {
157: /** todo
158: NodeMetadata node = getNodeMetadataService().getNode(id);
159: SAXBuilder builder = new SAXBuilder();
160:
161: try {
162: Document doc = builder.build(
163: getStreamStore().load(node, RepositoryNode.TECH_MD_TYPE));
164:
165: StructuredArtifact xmlObject =
166: new StructuredArtifact(doc.getRootElement(), getSchema().getChild(getRootNode()));
167:
168: xmlObject.setId(id);
169: xmlObject.setDisplayName(node.getName());
170: xmlObject.setHome(this);
171: xmlObject.setOwner(node.getOwner());
172:
173: return xmlObject;
174: } catch (Exception e) {
175: throw new SchemaInvalidException(e);
176: }
177: */
178: return null;
179: }
180:
181: public void remove(Artifact object) throws PersistenceException {
182: /**
183: getStreamStore().delete(getNodeMetadata(object.getId()));
184: getNodeMetadataService().delete(object.getId());
185: */
186: }
187:
188: public Artifact cloneArtifact(Artifact copy, String newName)
189: throws PersistenceException {
190: /** todo
191: NodeMetadata oldMetadata = getNodeMetadataService().getNode(copy.getId());
192: String origName = oldMetadata.getName();
193: oldMetadata.setName(newName);
194: NodeMetadata newMetadata = getNodeMetadataService().copyNode(oldMetadata);
195: oldMetadata.setName(origName);
196: getStreamStore().copyStreams(getNodeMetadataService().getNode(copy.getId()), newMetadata);
197:
198: return new LightweightArtifact(this, newMetadata);
199: */
200: return null;
201: }
202:
203: protected Artifact addArtifact(Artifact object)
204: throws PersistenceException {
205: StructuredArtifact artifact = (StructuredArtifact) object;
206: String newFileId = artifact.getParentFolder()
207: + getIdManager().createId().getValue();
208:
209: try {
210: ContentResourceEdit resource = ContentHostingService
211: .addResource(newFileId);
212: resource.setResourceType(FormResourceType.FORM_TYPE_ID);
213: ResourcePropertiesEdit resourceProperties = resource
214: .getPropertiesEdit();
215: resourceProperties.addProperty(
216: ResourceProperties.PROP_DISPLAY_NAME, object
217: .getDisplayName());
218: resourceProperties.addProperty(
219: ResourceProperties.PROP_DESCRIPTION, object
220: .getDisplayName());
221: resourceProperties.addProperty(
222: ResourceProperties.PROP_CONTENT_ENCODING, "UTF-8");
223: resourceProperties
224: .addProperty(
225: ResourceProperties.PROP_STRUCTOBJ_TYPE,
226: getTypeId());
227: resourceProperties.addProperty(
228: ResourceProperties.PROP_IS_COLLECTION,
229: Boolean.FALSE.toString());
230: resourceProperties
231: .addProperty(
232: ContentHostingService.PROP_ALTERNATE_REFERENCE,
233: org.sakaiproject.metaobj.shared.mgt.MetaobjEntityManager.METAOBJ_ENTITY_PREFIX);
234:
235: resource.setContent(getInfoBytes(artifact));
236: ContentHostingService.commitResource(resource);
237: artifact.setId(getIdManager().getId(
238: ContentHostingService.getUuid(newFileId)));
239: return object;
240: } catch (PermissionException e) {
241: throw new PersistenceException(
242: "No permission to write file", null, null);
243: } catch (IdUsedException e) {
244: throw new PersistenceException("Resource exists {0}",
245: new Object[] { artifact.getDisplayName() },
246: "displayName");
247: } catch (IdInvalidException e) {
248: throw new PersistenceException("Invalid name {0}",
249: new Object[] { artifact.getDisplayName() },
250: "displayName");
251: } catch (InconsistentException e) {
252: throw new PersistenceException("Invalid name {0}",
253: new Object[] { artifact.getDisplayName() },
254: "displayName");
255: } catch (ServerOverloadException e) {
256: throw new PersistenceException(e, "Unknown file error",
257: null, null);
258: } catch (OverQuotaException e) {
259: throw new PersistenceException("Over quota", null, null);
260: }
261: }
262:
263: /**
264: * protected InputStream getFileStream(StructuredArtifact xmlObject) {
265: * StringBuffer sb = new StringBuffer();
266: * <p/>
267: * format.format(new Object[]{getHostBaseUrl(), xmlObject.getId().getValue(),
268: * getType().getId().getValue(),
269: * getWorksiteManager().getCurrentWorksiteId() },
270: * sb, new FieldPosition(0));
271: * logger.debug("redirecting to: " + sb.toString());
272: * InputStream is = new ByteArrayInputStream(sb.toString().getBytes());
273: * <p/>
274: * return is;
275: * }
276: */
277:
278: protected byte[] getInfoBytes(Artifact object)
279: throws PersistenceException {
280:
281: XMLOutputter outputter = new XMLOutputter();
282: StructuredArtifact xmlObject = (StructuredArtifact) object;
283: ByteArrayOutputStream os = new ByteArrayOutputStream();
284:
285: try {
286: Format format = Format.getPrettyFormat();
287: outputter.setFormat(format);
288: outputter.output(xmlObject.getBaseElement(), os);
289: return os.toByteArray();
290: } catch (IOException e) {
291: throw new PersistenceException(e, "Unable to write object",
292: null, null);
293: }
294: }
295:
296: public byte[] getBytes(StructuredArtifact artifact) {
297: return getInfoBytes(artifact);
298: }
299:
300: protected InputStream getInfoStream(Artifact object)
301: throws PersistenceException {
302: return new ByteArrayInputStream(getInfoBytes(object));
303: }
304:
305: public String getHostBaseUrl() {
306: return Config.getInstance().getProperties().getProperty(
307: "baseUrl");
308: }
309:
310: public Element getArtifactAsXml(Artifact art) {
311: StructuredArtifact sa = (StructuredArtifact) art;
312:
313: Element root = new Element("artifact");
314: root.addContent(getMetadata(sa));
315:
316: Element data = new Element("structuredData");
317: Element baseElement = (Element) sa.getBaseElement().clone();
318: data.addContent(baseElement);
319: root.addContent(data);
320:
321: Element schemaData = new Element("schema");
322: schemaData.addContent(createInstructions());
323: schemaData.addContent(addSchemaInfo(getRootSchema()));
324:
325: // for now, don't call this... we may add this when
326: // we need to store id rather than ref... for now, keep
327: // this backward compatible with existing templates
328: // replaceFileRefs(schemaData, data);
329:
330: root.addContent(schemaData);
331:
332: return root;
333: }
334:
335: protected void replaceFileRefs(Element schemaData, Element data) {
336: try {
337: XPath fileAttachPath = XPath
338: .newInstance(".//element[@type='xs:anyURI']");
339: List fileElements = fileAttachPath.selectNodes(schemaData);
340: for (Iterator i = fileElements.iterator(); i.hasNext();) {
341: processFileElement((Element) i.next(), data);
342: }
343: } catch (JDOMException e) {
344: throw new RuntimeException(e);
345: }
346: }
347:
348: protected void processFileElement(Element element, Element data)
349: throws JDOMException {
350: String path = "";
351:
352: while (element != null) {
353: if (path.length() > 0) {
354: path = "/" + path;
355: }
356: path = element.getAttributeValue("name") + path;
357: element = element.getParentElement();
358: if (element != null) {
359: element = element.getParentElement();
360: }
361: }
362:
363: List fileElements = XPath.selectNodes(data, path);
364:
365: for (Iterator i = fileElements.iterator(); i.hasNext();) {
366: Element filePath = (Element) i.next();
367: String fileId = filePath.getTextTrim();
368: Artifact fileArt = getArtifactFinder().load(
369: getIdManager().getId(fileId));
370: PresentableObjectHome home = (PresentableObjectHome) fileArt
371: .getHome();
372: Element file = home.getArtifactAsXml(fileArt);
373: file.setName("artifact");
374: filePath.addContent(file);
375: }
376: }
377:
378: protected Element getMetadata(Artifact art) {
379: Element root = new Element("metaData");
380:
381: if (art.getId() != null) {
382: root.addContent(createNode("id", art.getId().getValue()));
383: }
384: root
385: .addContent(createNode("displayName", art
386: .getDisplayName()));
387:
388: Element type = new Element("type");
389: root.addContent(type);
390:
391: type.addContent(createNode("id", "file"));
392: type.addContent(createNode("description", "file"));
393:
394: ContentResource contentResource = ((StructuredArtifact) art)
395: .getBaseResource();
396: if (contentResource != null) {
397: Element repositoryNode = ContentHostingUtil
398: .createRepoNode(contentResource);
399: root.addContent(repositoryNode);
400: }
401:
402: return root;
403: }
404:
405: protected Element createNode(String name, String value) {
406: Element newNode = new Element(name);
407: newNode.addContent(value);
408: return newNode;
409: }
410:
411: protected Element createInstructions() {
412: Element instructions = new Element("instructions");
413: instructions.setContent(new CDATA(getInstruction()));
414: return instructions;
415: }
416:
417: protected Element addSchemaInfo(SchemaNode schema) {
418: Element schemaElement = new Element("element");
419: schemaElement.setAttribute("name", schema.getName());
420: if (schema.getType() != null
421: && schema.getType().getBaseType() != null) {
422: schemaElement.setAttribute("type", schema.getType()
423: .getBaseType());
424: }
425: schemaElement.setAttribute("minOccurs", schema.getMinOccurs()
426: + "");
427: schemaElement.setAttribute("maxOccurs", schema.getMaxOccurs()
428: + "");
429: Element annotation = schema.getSchemaElement().getChild(
430: "annotation", schema.getSchemaElement().getNamespace());
431:
432: if (annotation != null) {
433: schemaElement.addContent((Content) annotation.clone());
434: }
435:
436: Element simpleType = schema.getSchemaElement().getChild(
437: "simpleType", schema.getSchemaElement().getNamespace());
438:
439: if (simpleType != null) {
440: schemaElement.addContent((Content) simpleType.clone());
441: }
442:
443: List children = schema.getChildren();
444: Element childElement = new Element("children");
445: boolean found = false;
446: for (Iterator i = children.iterator(); i.hasNext();) {
447: childElement
448: .addContent(addSchemaInfo((SchemaNode) i.next()));
449: found = true;
450: }
451:
452: if (found) {
453: schemaElement.addContent(childElement);
454: }
455:
456: return schemaElement;
457: }
458:
459: public String getSiteId() {
460: return siteId;
461: }
462:
463: public void setSiteId(String siteId) {
464: this .siteId = siteId;
465: }
466:
467: public boolean isModifiable() {
468: return modifiable;
469: }
470:
471: /**
472: * @return true if SAD is global (available to all worksites)
473: */
474: public boolean isGlobal() {
475: return (getSiteId() == null || getSiteId().length() == 0);
476: }
477:
478: public PresentableObjectHome getRepositoryHelper() {
479: return repositoryHelper;
480: }
481:
482: public void setRepositoryHelper(
483: PresentableObjectHome repositoryHelper) {
484: this .repositoryHelper = repositoryHelper;
485: }
486:
487: public IdManager getIdManager() {
488: if (idManager == null) {
489: setIdManager((IdManager) ComponentManager.get("idManager"));
490: }
491: return idManager;
492: }
493:
494: public void setIdManager(IdManager idManager) {
495: this .idManager = idManager;
496: }
497:
498: public void setApplicationContext(
499: ApplicationContext applicationContext)
500: throws BeansException {
501: setIdManager((IdManager) applicationContext
502: .getBean("idManager"));
503: setRepositoryHelper((PresentableObjectHome) applicationContext
504: .getBean("repositoryHelper"));
505: }
506:
507: public int compareTo(Object o) {
508: StructuredArtifactHome that = (StructuredArtifactHome) o;
509: return this .getType().getDescription().toLowerCase().compareTo(
510: that.getType().getDescription().toLowerCase());
511: }
512:
513: public InputStream getStream(Id artifactId) {
514: try {
515: StructuredArtifact artifact = (StructuredArtifact) load(artifactId);
516: return getInfoStream(artifact);
517: } catch (PersistenceException e) {
518: throw new RuntimeException(e);
519: }
520: }
521:
522: public boolean isSystemOnly() {
523: return false;
524: }
525:
526: protected WorksiteManager getWorksiteManager() {
527: return (WorksiteManager) ComponentManager.getInstance().get(
528: WorksiteManager.class.getName());
529: }
530:
531: public ArtifactFinder getArtifactFinder() {
532: if (artifactFinder == null) {
533: setArtifactFinder((ArtifactFinder) ComponentManager
534: .get("org.sakaiproject.metaobj.shared.ArtifactFinder.fileArtifact"));
535: }
536: return artifactFinder;
537: }
538:
539: public void setArtifactFinder(ArtifactFinder artifactFinder) {
540: this.artifactFinder = artifactFinder;
541: }
542:
543: }
|