001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.xml.export;
019:
020: import java.io.File;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.io.Writer;
024: import java.util.Collection;
025: import java.util.HashSet;
026: import java.util.Iterator;
027: import java.util.Map;
028: import java.util.Set;
029: import java.util.TreeSet;
030:
031: import de.finix.contelligent.Component;
032: import de.finix.contelligent.ComponentContext;
033: import de.finix.contelligent.ComponentLink;
034: import de.finix.contelligent.ComponentManager;
035: import de.finix.contelligent.ComponentNotFoundException;
036: import de.finix.contelligent.ComponentPath;
037: import de.finix.contelligent.Type;
038: import de.finix.contelligent.category.Category;
039: import de.finix.contelligent.category.CategoryManager;
040: import de.finix.contelligent.content.BooleanContent;
041: import de.finix.contelligent.content.ContelligentContent;
042: import de.finix.contelligent.content.Content;
043: import de.finix.contelligent.content.ContentProvider;
044: import de.finix.contelligent.content.Metadata;
045: import de.finix.contelligent.core.ComponentContextImpl;
046: import de.finix.contelligent.core.ContelligentImpl;
047: import de.finix.contelligent.core.security.AccessControlList;
048: import de.finix.contelligent.core.security.AclEntry;
049: import de.finix.contelligent.core.security.ContelligentPrincipal;
050: import de.finix.contelligent.exception.ComponentPersistenceException;
051: import de.finix.contelligent.exception.TypeException;
052: import de.finix.contelligent.logging.LoggingService;
053: import de.finix.contelligent.render.ParameterDescription;
054: import de.finix.contelligent.render.Renderable;
055: import de.finix.contelligent.render.Renderer;
056: import de.finix.contelligent.render.TemplateRenderer;
057: import de.finix.contelligent.resource.BinaryResource;
058: import de.finix.contelligent.resource.NumberResource;
059: import de.finix.contelligent.resource.Resource;
060: import de.finix.contelligent.resource.StringResource;
061: import de.finix.contelligent.resource.TextResource;
062: import de.finix.contelligent.util.StringHash;
063: import de.finix.contelligent.util.StringUtils;
064: import de.finix.contelligent.xml.DTDCatalog;
065: import de.zeigermann.xml.XMLEncode;
066:
067: /**
068: * The default {@link ComponentXMLPolicy policy} for writing an XML
069: * representation of one component. Any binary content may be included into the
070: * XML or written to a separate file.
071: */
072: public class SingleComponentXMLPolicy implements ComponentXMLPolicy {
073:
074: final static org.apache.log4j.Logger log = LoggingService
075: .getLogger(SingleComponentXMLPolicy.class);
076:
077: protected int currentDepth = 0;
078:
079: protected String indent = " ";
080:
081: final protected File dir;
082:
083: /**
084: * Creates a new <code>SingleComponentXMLPolicy</code> instance. If
085: * <tt>dir</tt> is not null any binary resource is written into a separate
086: * file Note that any content writing is omited if {@link #includeContent}
087: * yields false.
088: *
089: * @param dir
090: * a <code>File</code> value
091: */
092: public SingleComponentXMLPolicy(File dir) {
093: this .dir = dir;
094: }
095:
096: public void writeXMLHeader(Writer writer) throws IOException {
097: DTDCatalog dtdCatalog = DTDCatalog.getInstance();
098: StringBuffer output = new StringBuffer(160);
099: output
100: .append(
101: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE ")
102: .append(DTDCatalog.COMPONENT_LIST)
103: .append(" PUBLIC \"")
104: .append(
105: dtdCatalog
106: .getPublicId(DTDCatalog.COMPONENT_LIST))
107: .append("\" \"")
108: .append(DTDCatalog.PUBLICID_URLPREFIX)
109: .append(
110: dtdCatalog
111: .getFileName(DTDCatalog.COMPONENT_LIST))
112: .append("\">\n\n").append("<").append(
113: DTDCatalog.COMPONENT_LIST).append(">\n");
114: writer.write(output.toString());
115: }
116:
117: public void writeXMLFooter(Writer writer) throws IOException {
118: writer.write("</" + DTDCatalog.COMPONENT_LIST + ">\n");
119: }
120:
121: // returns a set of String objects if any files were created by this method
122: // or else null
123: public Set writeComponent(Component component, Writer writer)
124: throws IOException, ComponentNotFoundException {
125: writeStartTag(component, writer);
126: incrementDepth();
127: writeMetainfo(component, writer);
128: try {
129: Type type = component.getComponentContext().getType();
130: Map componentPropertyMap = type.getProperties(component,
131: false, false);
132: writeProperties(componentPropertyMap, writer);
133: writeMetaContent(component, writer);
134: } catch (TypeException e) {
135: log.error("Could not read properties of component '"
136: + component + "'!", e);
137: }
138:
139: Set contentFiles = writeContent(component, writer);
140: Set renderFiles = writeRenderer(component, writer);
141: Set subFiles = writeSubcomponents(component, writer);
142: decrementDepth();
143: writeEndTag(component, writer);
144:
145: // first check for 'all are null' because this will be the most likely
146: // case (for client communication)
147: if (contentFiles != null || renderFiles != null
148: || subFiles != null) {
149: if (contentFiles != null) {
150: if (renderFiles != null)
151: contentFiles.addAll(renderFiles);
152: if (subFiles != null)
153: contentFiles.addAll(subFiles);
154: return contentFiles;
155: } else if (renderFiles != null) {
156: if (subFiles != null)
157: renderFiles.addAll(subFiles);
158: return renderFiles;
159: } else {
160: return subFiles;
161: }
162: } else {
163: return null;
164: }
165: }
166:
167: public void writeACL(AccessControlList acl, Writer writer)
168: throws ComponentNotFoundException, IOException {
169: writer.write("<meta-info>\n");
170: writeOwner(acl, writer);
171: writeACLEntries(null, acl, acl, writer);
172: writer.write("</meta-info>\n");
173:
174: }
175:
176: protected boolean followLinks() {
177: return false;
178: }
179:
180: protected boolean includeContent() {
181: return true;
182: }
183:
184: protected Set writeSubcomponents(Component component, Writer writer)
185: throws IOException, ComponentNotFoundException {
186: return null;
187: }
188:
189: protected void writeStartTag(Component component, Writer writer)
190: throws IOException {
191: ComponentContext ctx = component.getComponentContext();
192: ComponentPath path = ctx.getPath();
193: writer.write(indent);
194: writer.write("<component name=\"");
195: writer.write(path.getName());
196: writer.write('"');
197:
198: if (currentDepth == 0) {
199: writer.write(" dir=\"");
200: writer.write(path.getDir());
201: writer.write('"');
202: }
203:
204: writer.write(" type=\"");
205: writer.write(ctx.getType().getName());
206: writer.write("\"");
207:
208: // writer.write(" server=\"");
209: // writer.write(ctx.getPersistenceManager().getName());
210: // writer.write("\"");
211:
212: writeAdditionalStartTagAttributes(component, writer);
213: writer.write(">\n");
214: }
215:
216: protected void writeAdditionalStartTagAttributes(
217: Component component, Writer writer) throws IOException {
218: }
219:
220: // overwritten by ClientViewComponentXMLPolicy !!!
221: protected void writeAdditionalMetainfoTagAttributes(
222: Component component, Writer writer) throws IOException {
223: }
224:
225: protected void writeEndTag(Component component, Writer writer)
226: throws IOException {
227: writer.write(indent);
228: writer.write("</component>\n");
229: }
230:
231: // overwritten by ClientViewComponentXMLPolicy !!!
232: protected void writeMetainfo(Component component, Writer writer)
233: throws IOException {
234: ComponentContextImpl ctx = (ComponentContextImpl) component
235: .getComponentContext();
236: writer.write(indent);
237: writer.write("<meta-info lastModified=\"");
238: writer.write(String.valueOf(ctx.getLastModified()));
239: writer.write("\" isFinal=\"");
240: writer.write(String.valueOf(ctx.isFinal()));
241: writer.write("\"");
242:
243: writeAdditionalMetainfoTagAttributes(component, writer);
244:
245: String composedBlueprint = ctx.getComposedBlueprintName();
246: if (composedBlueprint != null) {
247: writer.write("\" composedBlueprint=\"");
248: writer.write(composedBlueprint);
249: writer.write("\"");
250: }
251: writer.write(">\n");
252: writer.write(indent);
253: writer.write("<security needsSecureTransfer=\"");
254: writer.write(String.valueOf(ctx.requiresSecureTransfer()));
255: writer.write("\" definesSecureTransfer=\"");
256: writer.write(String.valueOf(ctx.definesSecureTransfer()));
257: writer.write("\">\n");
258: incrementDepth();
259: writeOwner(ctx.getACL(), writer);
260: writeACLEntries(component, ctx.getACL(), ctx.getEffectiveACL(),
261: writer);
262: decrementDepth();
263: writer.write(indent);
264: writer.write("</security>\n");
265: writePublisher(component, writer);
266: writer.write(indent);
267: writer.write("</meta-info>\n");
268: }
269:
270: protected void writeOwner(AccessControlList acl, Writer writer)
271: throws IOException {
272: Set componentOwnerSet = acl.getOwners();
273: // XXX: this is a hack: normally every component should have an owner
274: // ...
275: // #oros: what are the reasons for a component to have an empty owner
276: // list?
277: if (componentOwnerSet.isEmpty()) {
278: // User defaultOwner = componentManager.getDefaultOwner();
279: // componentOwnerSet.add(defaultOwner);
280: log.warn("writeOwner() - ... ACL '" + acl
281: + "' has no owner!");
282: }
283:
284: Iterator owners = componentOwnerSet.iterator();
285:
286: while (owners.hasNext()) {
287: ContelligentPrincipal principal = (ContelligentPrincipal) owners
288: .next();
289: writer.write(indent);
290: writer.write("<owner principalGroupId=\"");
291: writer.write(principal.getGroupId());
292: writer.write("\" principalId=\"");
293: writer.write(principal.getName());
294: writer.write("\" />\n");
295: }
296:
297: owners = null;
298: }
299:
300: protected void writeACLEntries(Component component,
301: AccessControlList acl, AccessControlList effectiveAcl,
302: Writer writer) throws IOException {
303: Iterator aclEntries = acl.entrySet().iterator();
304:
305: while (aclEntries.hasNext()) {
306: AclEntry currentEntry = (AclEntry) aclEntries.next();
307: ContelligentPrincipal principal = currentEntry
308: .getPrincipal();
309: writer.write(indent);
310: writer.write("<access principalGroupId=\"");
311: writer.write(principal.getGroupId());
312: writer.write("\" principalId=\"");
313: writer.write(principal.getName());
314: writer.write("\" accessType=\"");
315: writer.write(currentEntry.getPermission().toString());
316: writer.write("\" mode=\"");
317: writer.write(currentEntry.getMode().toString());
318: writer.write("\" validFrom=\"");
319: writer.write(Long.toString(currentEntry.getValidFrom()));
320: writer.write("\" validTo=\"");
321: writer.write(Long.toString(currentEntry.getValidTo()));
322: writer.write("\" period=\"");
323: writer.write(Long.toString(currentEntry.getPeriod()));
324: writer.write("\" duration=\"");
325: writer.write(Long.toString(currentEntry.getDuration()));
326: writer.write("\" />\n");
327: }
328: }
329:
330: protected void writeProperties(Map componentPropertyMap,
331: Writer writer) throws IOException {
332: Iterator it = componentPropertyMap.entrySet().iterator();
333: while (it.hasNext()) {
334: Map.Entry entry = (Map.Entry) it.next();
335: String propertyName = (String) entry.getKey();
336: Object propertyValue = entry.getValue();
337: writer.write(indent);
338: writer.write("<component-property name=\"");
339: writer.write(propertyName);
340: writer.write("\"><![CDATA[");
341: writer.write(DefaultTypeXMLPolicy
342: .propertyValueToString(propertyValue));
343: writer.write("]]></component-property>\n");
344: }
345: }
346:
347: protected void writeMetaContent(Component comp, Writer writer)
348: throws IOException {
349: Metadata metadata = comp.getComponentContext().getMetadata();
350: Iterator keys = new TreeSet(metadata.getKeys()).iterator();
351: while (keys.hasNext()) {
352: String key = (String) keys.next();
353: Iterator values = metadata.getValues(key).iterator();
354: while (values.hasNext()) {
355: String value = (String) values.next();
356: writer.write(indent);
357: writer.write("<metadata><key><![CDATA[");
358: writer.write(key);
359: writer.write("]]></key><value><![CDATA[");
360: writer.write(value);
361: writer.write("]]></value></metadata>\n");
362: }
363: }
364: }
365:
366: protected void writePublisher(Component comp, Writer writer)
367: throws IOException {
368: ComponentContext cc = comp.getComponentContext();
369: if (cc instanceof ComponentContextImpl) {
370: ComponentContextImpl cci = (ComponentContextImpl) cc;
371: String pName = cci.getPublisherName();
372: String pType = cci.getPublisherType();
373: if ((pName.length() > 0) && (pType.length() > 0)) {
374: if (pType.equals("basic")) {
375: writer.write(indent);
376: writer.write("<publisher>");
377: String sourceText = StringUtils.concat(comp
378: .getComponentContext().getPath().toPath(),
379: "#c1#", pName);
380: String pData = StringHash.getHash(sourceText);
381: writer.write("<basic name=\"");
382: writer.write(pName);
383: writer.write("\" data=\"");
384: writer.write(pData);
385: writer.write("\"/>");
386: writer.write("</publisher>\n");
387: }
388: }
389: }
390: }
391:
392: // returns a set of String objects if any files were created by this method
393: // or else null
394: protected Set writeContent(Component component, Writer writer)
395: throws IOException {
396: Set createdFiles = null;
397: if (log.isDebugEnabled()) {
398: log.debug("... including content of component '"
399: + component + "' ...");
400: }
401: if (component instanceof ContentProvider
402: && ((ContentProvider) component).getContent() instanceof ContelligentContent) {
403: Content content = ((ContentProvider) component)
404: .getContent();
405: writer.write(indent);
406: writer.write("<content>\n");
407: incrementDepth();
408: Collection sensitiveCategories = content
409: .getSensitiveCategories();
410: Iterator iterator = sensitiveCategories.iterator();
411: while (iterator.hasNext()) {
412: Category category = (Category) iterator.next();
413: writer.write(indent);
414: writer.write("<sensitive-category name=\""
415: + category.getName());
416: writer.write("\" supportedValues=\"");
417: int numberOfValues = category.getSupportedValues().length;
418: String[] supportedValues = category
419: .getSupportedValues();
420: for (int i = 0; i < numberOfValues; i++) {
421: writer.write(supportedValues[i]);
422: if (i < numberOfValues - 1) {
423: writer.write(',');
424: }
425: }
426: writer.write("\" />\n");
427: }
428: try {
429: Collection definedResources = component
430: .getComponentContext()
431: .getContentResourceIdentifiers();
432: Map allPossibleCombinations = ContelligentImpl
433: .getInstance().getCategoryManager()
434: .getSensitveCategoryCombinations(
435: sensitiveCategories);
436: for (Iterator i = definedResources.iterator(); i
437: .hasNext();) {
438: String identifier = (String) i.next();
439: Map categoryMap = (Map) allPossibleCombinations
440: .get(identifier);
441: writer.write(indent);
442: writer.write("<resource>\n");
443: incrementDepth();
444: if (categoryMap != null) {
445: for (Iterator j = categoryMap.entrySet()
446: .iterator(); j.hasNext();) {
447: Map.Entry category = (Map.Entry) j.next();
448: String categoryName = (String) category
449: .getKey();
450: String categoryValue = (String) category
451: .getValue();
452: writer.write(indent);
453: writer.write("<supported-category name=\"");
454: writer.write(categoryName);
455: writer.write("\" value=\"");
456: writer.write(categoryValue);
457: writer.write("\" />\n");
458: }
459: }
460: Resource resource = component.getComponentContext()
461: .getContentResource(identifier);
462: writer.write(indent);
463: String file = writeResource(component, content,
464: identifier, resource, writer);
465: if (file != null) {
466: if (createdFiles == null)
467: createdFiles = new HashSet();
468: createdFiles.add(file);
469: }
470: decrementDepth();
471: writer.write(indent);
472: writer.write("</resource>\n");
473: }
474: } catch (ComponentPersistenceException e) {
475: log
476: .error(
477: "writeContent(): Could not get content resource!",
478: e);
479: }
480: decrementDepth();
481: writer.write(indent);
482: writer.write("</content>\n");
483: }
484: return createdFiles;
485: }
486:
487: // returns a set of String objects if any files were created by this method
488: // or else null
489: protected Set writeRenderer(Component component, Writer writer)
490: throws IOException {
491: Set createdFiles = null;
492: if (log.isDebugEnabled()) {
493: log.debug("... including templates of component '"
494: + component + "' ...");
495: }
496: if (component instanceof Renderable) {
497: Renderer renderer = ((Renderable) component).getRenderer();
498: writer.write(indent);
499: writer.write("<renderer");
500: if (renderer instanceof TemplateRenderer) {
501: writer.write(" type=\""
502: + ((TemplateRenderer) renderer).getTypeName()
503: + "\"");
504: }
505: writer.write(">\n");
506: incrementDepth();
507: ParameterDescription[] parameter = renderer
508: .getParameterDescription();
509: if (parameter != null) {
510: for (int i = 0; i < parameter.length; i++) {
511: writer.write(indent);
512: writer.write("<parameter-description name=\"");
513: writer.write(parameter[i].getName());
514: writer.write("\" description=\"");
515: writer.write(parameter[i].getDescription());
516: writer.write("\" isRequired=\"");
517: writer.write(String.valueOf(parameter[i]
518: .isRequired()));
519: writer.write("\"");
520: String[] allowedValues = parameter[i]
521: .getAllowedValues();
522: if (allowedValues == null) {
523: writer.write("/>\n");
524: } else {
525: writer.write(">\n");
526: incrementDepth();
527: for (int j = 0; j < allowedValues.length; j++) {
528: writer.write(indent);
529: writer.write("<allowed-value><![CDATA[");
530: writer.write(allowedValues[j]);
531: writer.write("]]></allowed-value>\n");
532: }
533: decrementDepth();
534: writer.write(indent);
535: writer.write("</parameter-description>\n");
536: }
537: }
538: }
539: Collection sensitiveCategories = renderer
540: .getSensitiveCategories();
541: if (sensitiveCategories != null) {
542: Iterator iterator = sensitiveCategories.iterator();
543: while (iterator.hasNext()) {
544: Category category = (Category) iterator.next();
545: writer.write(indent);
546: writer.write("<sensitive-category name=\""
547: + category.getName());
548: writer.write("\" supportedValues=\"");
549: int numberOfValues = category.getSupportedValues().length;
550: String[] supportedValues = category
551: .getSupportedValues();
552: for (int i = 0; i < numberOfValues; i++) {
553: writer.write(supportedValues[i]);
554: if (i < numberOfValues - 1) {
555: writer.write(',');
556: }
557: }
558: writer.write("\" />\n");
559: }
560: }
561: try {
562: // XXX: we may safely use the root-manager here because whether
563: // a component defines a blueprint or not
564: // or whether it is a blueprint instance is solely determined by
565: // the type. And since types are
566: // (currently) global we may ask the root-manager.
567: ComponentManager manager = ContelligentImpl
568: .getInstance().getRootComponentManager();
569: if (manager.definesBlueprint(component)
570: || !manager.isBlueprintInstance(component)) {
571: Collection definedResources = component
572: .getComponentContext()
573: .getTemplateResourceIdentifiers();
574: Map allPossibleCombinations = ContelligentImpl
575: .getInstance().getCategoryManager()
576: .getSensitveCategoryCombinations(
577: sensitiveCategories);
578: for (Iterator i = definedResources.iterator(); i
579: .hasNext();) {
580: String identifier = (String) i.next();
581: Map categoryMap = (Map) allPossibleCombinations
582: .get(identifier);
583: writer.write(indent);
584: writer.write("<resource>\n");
585: incrementDepth();
586: if (categoryMap != null) {
587: for (Iterator j = categoryMap.entrySet()
588: .iterator(); j.hasNext();) {
589: Map.Entry category = (Map.Entry) j
590: .next();
591: String categoryName = (String) category
592: .getKey();
593: String categoryValue = (String) category
594: .getValue();
595: writer.write(indent);
596: writer
597: .write("<supported-category name=\"");
598: writer.write(categoryName);
599: writer.write("\" value=\"");
600: writer.write(categoryValue);
601: writer.write("\" />\n");
602: }
603: }
604: writer.write(indent);
605: String file = writeResource(
606: component,
607: identifier,
608: component
609: .getComponentContext()
610: .getTemplateResource(identifier),
611: writer);
612: if (file != null) {
613: if (createdFiles == null)
614: createdFiles = new HashSet();
615: createdFiles.add(file);
616: }
617: decrementDepth();
618: writer.write(indent);
619: writer.write("</resource>\n");
620: }
621: }
622: } catch (ComponentPersistenceException e) {
623: log
624: .error(
625: "writeRenderer(): Could not get template resource!",
626: e);
627: }
628: decrementDepth();
629: writer.write(indent);
630: writer.write("</renderer>\n");
631: }
632: // Support parameters for the special case of CurrentPage
633: if (component instanceof ComponentLink) {
634: ComponentLink renderer = (ComponentLink) component;
635: writer.write(indent);
636: writer.write("<renderer>\n");
637: incrementDepth();
638: ParameterDescription[] parameter = renderer
639: .getParameterDescription();
640: if (parameter != null) {
641: for (int i = 0; i < parameter.length; i++) {
642: writer.write(indent);
643: writer.write("<parameter-description name=\"");
644: writer.write(parameter[i].getName());
645: writer.write("\" description=\"");
646: writer.write(parameter[i].getDescription());
647: writer.write("\" isRequired=\"");
648: writer.write(String.valueOf(parameter[i]
649: .isRequired()));
650: writer.write("\"");
651: String[] allowedValues = parameter[i]
652: .getAllowedValues();
653: if (allowedValues == null) {
654: writer.write("/>\n");
655: } else {
656: writer.write(">\n");
657: incrementDepth();
658: for (int j = 0; j < allowedValues.length; j++) {
659: writer.write(indent);
660: writer.write("<allowed-value><![CDATA[");
661: writer.write(allowedValues[j]);
662: writer.write("]]></allowed-value>\n");
663: }
664: decrementDepth();
665: writer.write(indent);
666: writer.write("</parameter-description>\n");
667: }
668: }
669: }
670: decrementDepth();
671: writer.write(indent);
672: writer.write("</renderer>\n");
673: }
674: return createdFiles;
675: }
676:
677: protected String writeResource(Component component,
678: String identifier, Resource resource, Writer writer)
679: throws IOException, ComponentPersistenceException {
680: return writeResource(component, null, identifier, resource,
681: writer);
682: }
683:
684: protected String writeResource(Component component,
685: Content content, String identifier, Resource resource,
686: Writer writer) throws IOException,
687: ComponentPersistenceException {
688: if (resource instanceof TextResource) {
689: writer.write("<text>");
690: writer.write(XMLEncode
691: .xmlEncodeTextAsPCDATA(((TextResource) resource)
692: .getString()));
693: writer.write("</text>\n");
694: } else if (resource instanceof StringResource) {
695: // FIXME if boolean resources are supported remove this ugly code:
696: if (content != null && content instanceof BooleanContent) {
697: writer.write("<boolean value=\"");
698: writer.write(((StringResource) resource).getString());
699: writer.write("\" />\n");
700: } else {
701: if (resource.getConstraints() == null) {
702: writer.write("<string>");
703: } else {
704: writer.write("<string constraints=\"");
705: writer.write(resource.getConstraints());
706: writer.write("\">");
707: }
708: writer
709: .write(XMLEncode
710: .xmlEncodeTextAsPCDATA(((StringResource) resource)
711: .getString()));
712: writer.write("</string>\n");
713: }
714: } else if (resource instanceof NumberResource) {
715: if (resource.getConstraints() == null) {
716: writer.write("<number>");
717: } else {
718: writer.write("<number constraints=\"");
719: writer.write(resource.getConstraints());
720: writer.write("\">");
721: }
722: writer.write(((NumberResource) resource).getNumber()
723: .toString());
724: writer.write("</number>\n");
725: } else if (resource instanceof BinaryResource) {
726: BinaryResource binaryResource = (BinaryResource) resource;
727: StringBuffer fileName = new StringBuffer(component
728: .getComponentContext().getPath().toString());
729: fileName.append(
730: identifier.replace(
731: CategoryManager.IDENTIFIER_SEPARATOR, '%'))
732: .append('.').append(binaryResource.getExtension());
733: writer.write("<binary contentType=\"");
734: writer.write(binaryResource.getContentType());
735: writer.write("\" extension=\"");
736: writer.write(binaryResource.getExtension());
737: writer.write("\" src=\"");
738: writer.write(fileName.toString());
739: writer.write("\"/>\n");
740: if (dir != null) {
741: File resourceFile = new File(dir, fileName.toString());
742: resourceFile.getParentFile().mkdirs();
743: FileOutputStream out = new FileOutputStream(
744: resourceFile);
745: binaryResource.stream(out);
746: out.close();
747: log.debug("writeResource() - created file '"
748: + resourceFile + "'.");
749: return fileName.toString();
750: } else {
751: if (log.isDebugEnabled()) // this is normal behaviour in
752: // server-client communication:
753: log
754: .debug("writeResource() - cannot write file for binary resource of component '"
755: + component
756: + "' because dir is null!");
757: }
758: } else {
759: log.warn("writeResource() - ignoring resource '"
760: + identifier + "' of component '" + component
761: + "' because its type is not supported. (class="
762: + resource.getClass() + ")");
763: }
764: return null;
765: }
766:
767: protected void incrementDepth() {
768: currentDepth++;
769: indent = indent + " ";
770: }
771:
772: protected void decrementDepth() {
773: currentDepth--;
774: indent = indent.substring(0, indent.length() - 3);
775: }
776:
777: protected int maxDepth() {
778: return 0;
779: }
780:
781: }
|