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: */
018: package org.apache.lenya.cms.jcr.metadata;
019:
020: import java.io.OutputStream;
021: import java.util.ArrayList;
022: import java.util.Arrays;
023: import java.util.HashMap;
024: import java.util.List;
025: import java.util.Map;
026:
027: import javax.jcr.Node;
028: import javax.jcr.Property;
029: import javax.jcr.Value;
030:
031: import org.apache.avalon.framework.container.ContainerUtil;
032: import org.apache.avalon.framework.logger.AbstractLogEnabled;
033: import org.apache.avalon.framework.logger.Logger;
034: import org.apache.avalon.framework.service.ServiceManager;
035: import org.apache.cocoon.jcr.source.JCRNodeSource;
036: import org.apache.excalibur.source.SourceResolver;
037: import org.apache.lenya.cms.metadata.ElementSet;
038: import org.apache.lenya.cms.metadata.MetaData;
039: import org.apache.lenya.cms.metadata.MetaDataException;
040: import org.apache.lenya.cms.publication.DocumentException;
041: import org.apache.lenya.cms.repository.RepositoryException;
042:
043: /**
044: * JCR based meta data.
045: */
046: public class JCRMetaData extends AbstractLogEnabled implements MetaData {
047:
048: private String namespace;
049: private String sourceUri;
050: protected ServiceManager manager;
051:
052: private Map key2values = null;
053:
054: /**
055: * Ctor.
056: * @param namespace
057: * @param sourceUri
058: * @param manager
059: * @param logger
060: */
061: public JCRMetaData(String namespace, String sourceUri,
062: ServiceManager manager, Logger logger) {
063: this .namespace = namespace;
064: this .sourceUri = sourceUri;
065: this .manager = manager;
066: ContainerUtil.enableLogging(this , logger);
067: }
068:
069: protected Map getKey2Values() {
070: if (this .key2values == null) {
071: load();
072: }
073: return this .key2values;
074: }
075:
076: protected void load() {
077:
078: this .key2values = new HashMap();
079: SourceResolver resolver = null;
080: JCRNodeSource source = null;
081: try {
082: resolver = (SourceResolver) this .manager
083: .lookup(SourceResolver.ROLE);
084: source = (JCRNodeSource) resolver
085: .resolveURI(this .sourceUri);
086:
087: Node node = source.getNode();
088: String prefix = node.getSession().getWorkspace()
089: .getNamespaceRegistry().getPrefix(this .namespace);
090: if (!prefix.equals("")) {
091: prefix = prefix + ":";
092: }
093:
094: String possibleKeys[] = getPossibleKeys();
095: for (int i = 0; i < possibleKeys.length; i++) {
096: String key = prefix + possibleKeys[i];
097: if (node.hasProperty(key)) {
098: Property property = node.getProperty(key);
099: Value[] values = property.getValues();
100: String[] stringValues = new String[values.length];
101: for (int v = 0; v < values.length; v++) {
102: stringValues[v] = values[v].getString();
103: }
104: this .key2values.put(possibleKeys[i], stringValues);
105: }
106: }
107:
108: } catch (Exception e) {
109: throw new RuntimeException(e);
110: } finally {
111: if (resolver != null) {
112: if (source != null) {
113: resolver.release(source);
114: }
115: this .manager.release(resolver);
116: }
117: }
118: }
119:
120: public void save() throws MetaDataException {
121: SourceResolver resolver = null;
122: JCRNodeSource source = null;
123: try {
124: resolver = (SourceResolver) this .manager
125: .lookup(SourceResolver.ROLE);
126: source = (JCRNodeSource) resolver
127: .resolveURI(this .sourceUri);
128:
129: if (!source.exists()) {
130: OutputStream stream = source.getOutputStream();
131: stream.flush();
132: stream.close();
133: }
134:
135: Node node = source.getNode();
136: String prefix = node.getSession().getWorkspace()
137: .getNamespaceRegistry().getPrefix(this .namespace);
138: if (!prefix.equals("")) {
139: prefix = prefix + ":";
140: }
141:
142: String possibleKeys[] = getPossibleKeys();
143: for (int i = 0; i < possibleKeys.length; i++) {
144: String[] stringValues = (String[]) getKey2Values().get(
145: possibleKeys[i]);
146: String key = prefix + possibleKeys[i];
147: node.setProperty(key, stringValues);
148: }
149:
150: } catch (Exception e) {
151: throw new RuntimeException(e);
152: } finally {
153: if (resolver != null) {
154: if (source != null) {
155: resolver.release(source);
156: }
157: this .manager.release(resolver);
158: }
159: }
160: }
161:
162: public String[] getValues(String key) throws MetaDataException {
163: return (String[]) getKey2Values().get(key);
164: }
165:
166: public String getFirstValue(String key) throws MetaDataException {
167: String value = null;
168: String[] values = (String[]) getKey2Values().get(key);
169: if (values.length > 0) {
170: value = values[0];
171: }
172: return value;
173: }
174:
175: public void setValue(String key, String value)
176: throws MetaDataException {
177: String[] values = { value };
178: getKey2Values().put(key, values);
179: }
180:
181: public void addValue(String key, String value)
182: throws MetaDataException {
183: String[] values = (String[]) getKey2Values().get(key);
184: List valueList = new ArrayList(Arrays.asList(values));
185: valueList.add(value);
186: values = (String[]) valueList.toArray(new String[valueList
187: .size()]);
188: getKey2Values().put(key, values);
189: }
190:
191: public void replaceBy(MetaData other) throws MetaDataException {
192: this .key2values = new HashMap();
193: String[] keys = getPossibleKeys();
194: for (int i = 0; i < keys.length; i++) {
195: String[] values = other.getValues(keys[i]);
196: this .key2values.put(keys[i], values);
197: }
198: save();
199: }
200:
201: public void forcedReplaceBy(MetaData other)
202: throws MetaDataException {
203: replaceBy(other);
204: }
205:
206: private String[] possibleKeys = new String[0];
207:
208: /**
209: * @param keys The possible keys.
210: */
211: public void setPossibleKeys(String[] keys) {
212: this .possibleKeys = keys;
213: }
214:
215: public String[] getPossibleKeys() {
216: return this .possibleKeys;
217: }
218:
219: public boolean isValidAttribute(String key) {
220: String[] keys = getPossibleKeys();
221: return Arrays.asList(keys).contains(key);
222: }
223:
224: public HashMap getAvailableKey2Value() {
225: // TODO We need to implement this Method!
226: return null;
227: }
228:
229: public long getLastModified() throws MetaDataException {
230: long lastModified = 0;
231: try {
232: SourceResolver resolver = (SourceResolver) this .manager
233: .lookup(SourceResolver.ROLE);
234: JCRNodeSource source = (JCRNodeSource) resolver
235: .resolveURI(this .sourceUri);
236: lastModified = source.getLastModified();
237: } catch (Exception e) {
238: throw new MetaDataException(
239: "Error resolving meta data source", e);
240: }
241: return lastModified;
242: }
243:
244: public String[] getAvailableKeys() {
245: throw new RuntimeException("not implemented");
246: }
247:
248: public ElementSet getElementSet() {
249: throw new RuntimeException("not implemented");
250: }
251:
252: public void removeAllValues(String key) throws MetaDataException {
253: throw new RuntimeException("not implemented");
254: }
255: }
|