blob: 2e54a0959ca8589cff16fd484d7c3e5a18ac8e7c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.lenya.cms.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.lenya.cms.cocoon.source.SourceUtil;
import org.apache.lenya.cms.metadata.ElementSet;
import org.apache.lenya.cms.metadata.MetaData;
import org.apache.lenya.cms.metadata.MetaDataException;
import org.apache.lenya.cms.metadata.MetaDataOwner;
import org.apache.lenya.cms.metadata.MetaDataRegistry;
import org.apache.lenya.cms.metadata.dublincore.DublinCore;
import org.apache.lenya.cms.publication.PageEnvelope;
import org.apache.lenya.xml.DocumentHelper;
import org.apache.lenya.xml.NamespaceHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Handles the meta data of source nodes.
*/
public class SourceNodeMetaDataHandler implements MetaDataOwner {
private ServiceManager manager;
private String sourceUri;
/**
* @param manager The service manager.
* @param sourceUri The soure URI.
*/
public SourceNodeMetaDataHandler(ServiceManager manager, String sourceUri) {
this.manager = manager;
this.sourceUri = sourceUri;
}
private Map namespace2metadata = new HashMap();
public MetaData getMetaData(String namespaceUri) throws MetaDataException {
MetaData meta = (MetaData) this.namespace2metadata.get(namespaceUri);
if (meta == null) {
MetaDataRegistry registry = null;
try {
registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
if (!registry.isRegistered(namespaceUri)) {
throw new MetaDataException("The namespace [" + namespaceUri
+ "] is not registered!");
}
} catch (ServiceException e) {
throw new MetaDataException(e);
} finally {
if (registry != null) {
this.manager.release(registry);
}
}
synchronized (this) {
meta = new SourceNodeMetaData(namespaceUri, this, this.manager);
this.namespace2metadata.put(namespaceUri, meta);
}
}
return meta;
}
protected Map namespace2metamap = null;
protected synchronized Map getMetaDataMap(String namespaceUri) throws MetaDataException {
if (this.namespace2metamap == null) {
loadMetaData();
}
Map map = (Map) this.namespace2metamap.get(namespaceUri);
if (map == null) {
map = new HashMap();
this.namespace2metamap.put(namespaceUri, map);
}
return map;
}
protected static final String META_DATA_NAMESPACE = "http://apache.org/lenya/metadata/1.0";
protected static final String ELEMENT_METADATA = "metadata";
protected static final String ELEMENT_SET = "element-set";
protected static final String ELEMENT_ELEMENT = "element";
protected static final String ELEMENT_VALUE = "value";
protected static final String ATTRIBUTE_NAMESPACE = "namespace";
protected static final String ATTRIBUTE_KEY = "key";
protected synchronized void loadMetaData() throws MetaDataException {
if (this.namespace2metamap != null) {
throw new IllegalStateException("The meta data have already been loaded!");
}
try {
this.namespace2metamap = new HashMap();
if (SourceUtil.exists(this.sourceUri, this.manager)) {
Document xml = SourceUtil.readDOM(this.sourceUri, this.manager);
if (!xml.getDocumentElement().getNamespaceURI().equals(META_DATA_NAMESPACE)) {
loadLegacyMetaData(xml);
} else {
NamespaceHelper helper = new NamespaceHelper(META_DATA_NAMESPACE, "", xml);
Element[] setElements = helper.getChildren(xml.getDocumentElement(),
ELEMENT_SET);
for (int setIndex = 0; setIndex < setElements.length; setIndex++) {
String namespace = setElements[setIndex].getAttribute(ATTRIBUTE_NAMESPACE);
Element[] elementElements = helper.getChildren(setElements[setIndex],
ELEMENT_ELEMENT);
Map element2values = new HashMap();
for (int elemIndex = 0; elemIndex < elementElements.length; elemIndex++) {
String key = elementElements[elemIndex].getAttribute(ATTRIBUTE_KEY);
Element[] valueElements = helper.getChildren(
elementElements[elemIndex], ELEMENT_VALUE);
List values = new ArrayList();
for (int valueIndex = 0; valueIndex < valueElements.length; valueIndex++) {
String value = DocumentHelper
.getSimpleElementText(valueElements[valueIndex]);
values.add(value);
}
element2values.put(key, values);
}
this.namespace2metamap.put(namespace, element2values);
}
}
}
} catch (Exception e) {
throw new MetaDataException(e);
}
}
protected void loadLegacyMetaData(Document xml) throws MetaDataException {
NamespaceHelper helper = new NamespaceHelper(PageEnvelope.NAMESPACE, "", xml);
Element metaElement = helper.getFirstChild(xml.getDocumentElement(), "meta");
Element internalElement = helper.getFirstChild(metaElement, "internal");
Element[] internalElements = helper.getChildren(internalElement);
for (int i = 0; i < internalElements.length; i++) {
String value = DocumentHelper.getSimpleElementText(internalElements[i]);
String key = internalElements[i].getLocalName();
if (key.equals("workflowVersion")) {
List values = getValueList("http://apache.org/lenya/metadata/workflow/1.0", key);
values.add(value);
} else {
List values = getValueList("http://apache.org/lenya/metadata/document/1.0", key);
values.add(value);
}
}
NamespaceHelper dcHelper = new NamespaceHelper(DublinCore.DC_NAMESPACE, "", xml);
Element dcElement = helper.getFirstChild(metaElement, "dc");
if (dcElement != null) {
MetaDataRegistry registry = null;
try {
registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
ElementSet dcElementSet = registry.getElementSet(DublinCore.DC_NAMESPACE);
ElementSet dcTermSet = registry.getElementSet(DublinCore.DCTERMS_NAMESPACE);
Element[] dcElements = dcHelper.getChildren(dcElement);
for (int i = 0; i < dcElements.length; i++) {
String value = DocumentHelper.getSimpleElementText(dcElements[i]);
String key = dcElements[i].getLocalName();
if (dcElementSet.containsElement(key)) {
List values = getValueList(DublinCore.DC_NAMESPACE, key);
values.add(value);
} else if (dcTermSet.containsElement(key)) {
List values = getValueList(DublinCore.DCTERMS_NAMESPACE, key);
values.add(value);
} else {
throw new RepositoryException("The dublin core key [" + key
+ "] is not supported.");
}
}
} catch (MetaDataException e) {
throw e;
} catch (Exception e) {
throw new MetaDataException(e);
} finally {
if (registry != null) {
this.manager.release(registry);
}
}
}
}
protected String[] getValues(String namespaceUri, String key, int revisionNumber)
throws MetaDataException {
List values = getValueList(namespaceUri, key);
return (String[]) values.toArray(new String[values.size()]);
}
protected String[] getValues(String namespaceUri, String key) throws MetaDataException {
List values = getValueList(namespaceUri, key);
return (String[]) values.toArray(new String[values.size()]);
}
protected List getValueList(String namespaceUri, String key) throws MetaDataException {
Map map = getMetaDataMap(namespaceUri);
List values = (List) map.get(key);
if (values == null) {
synchronized (this) {
values = new ArrayList();
map.put(key, values);
}
}
return values;
}
protected void addValue(String namespaceUri, String key, String value) throws MetaDataException {
throw new IllegalStateException("Operation not supported");
}
protected void removeAllValues(String namespaceUri, String key) throws MetaDataException {
throw new IllegalStateException("Operation not supported");
}
protected void setValue(String namespaceUri, String key, String value) throws MetaDataException {
throw new IllegalStateException("Operation not supported");
}
public String[] getMetaDataNamespaceUris() throws MetaDataException {
MetaDataRegistry registry = null;
try {
registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
return registry.getNamespaceUris();
} catch (ServiceException e) {
throw new MetaDataException(e);
} finally {
if (registry != null) {
this.manager.release(registry);
}
}
}
protected long getLastModified() throws RepositoryException {
try {
return SourceUtil.getLastModified(this.sourceUri, this.manager);
} catch (Exception e) {
throw new RepositoryException(e);
}
}
}