001/*
002 * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Thierry Delprat
019 */
020package org.nuxeo.apidoc.introspection;
021
022import java.io.File;
023import java.io.FileInputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.net.URL;
027import java.nio.charset.StandardCharsets;
028import java.util.ArrayList;
029import java.util.Collection;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033import java.util.zip.ZipEntry;
034import java.util.zip.ZipFile;
035
036import org.apache.commons.io.FileUtils;
037import org.apache.commons.io.IOUtils;
038import org.apache.commons.logging.Log;
039import org.apache.commons.logging.LogFactory;
040import org.nuxeo.apidoc.api.BaseNuxeoArtifact;
041import org.nuxeo.apidoc.api.BundleInfo;
042import org.nuxeo.apidoc.api.ComponentInfo;
043import org.nuxeo.apidoc.api.ExtensionInfo;
044import org.nuxeo.apidoc.api.ExtensionPointInfo;
045import org.nuxeo.apidoc.api.ServiceInfo;
046import org.nuxeo.apidoc.documentation.DocumentationHelper;
047import org.nuxeo.common.utils.Path;
048
049public class ComponentInfoImpl extends BaseNuxeoArtifact implements ComponentInfo {
050
051    protected final BundleInfo bundle;
052
053    protected final String name;
054
055    protected final Map<String, ExtensionPointInfo> extensionPoints;
056
057    protected final Collection<ExtensionInfo> extensions;
058
059    protected final List<String> serviceNames = new ArrayList<>();
060
061    protected final List<ServiceInfo> services = new ArrayList<>();
062
063    protected URL xmlFileUrl;
064
065    protected String componentClass;
066
067    protected String documentation; // TODO
068
069    protected static final Log log = LogFactory.getLog(ComponentInfoImpl.class);
070
071    public ComponentInfoImpl(BundleInfo bundleInfo, String name) {
072        bundle = bundleInfo;
073        this.name = name;
074        extensionPoints = new HashMap<>();
075        extensions = new ArrayList<>();
076    }
077
078    @Override
079    public String getName() {
080        return name;
081    }
082
083    @Override
084    public BundleInfo getBundle() {
085        return bundle;
086    }
087
088    @Override
089    public Collection<ExtensionPointInfo> getExtensionPoints() {
090        return extensionPoints.values();
091    }
092
093    @Override
094    public Collection<ExtensionInfo> getExtensions() {
095        return extensions;
096    }
097
098    public void addExtensionPoint(ExtensionPointInfoImpl xp) {
099        extensionPoints.put(xp.getId(), xp);
100    }
101
102    @Override
103    public ExtensionPointInfo getExtensionPoint(String name) {
104        return extensionPoints.get(name);
105    }
106
107    public void addExtension(ExtensionInfoImpl xt) {
108        extensions.add(xt);
109    }
110
111    @Override
112    public String getDocumentation() {
113        return documentation;
114    }
115
116    @Override
117    public String getDocumentationHtml() {
118        return DocumentationHelper.getHtml(getDocumentation());
119    }
120
121    public void setDocumentation(String documentation) {
122        this.documentation = documentation;
123    }
124
125    public void addService(String serviceName, boolean overriden) {
126        serviceNames.add(serviceName);
127        ServiceInfo si = new ServiceInfoImpl(serviceName, overriden, this);
128        services.add(si);
129    }
130
131    @Override
132    public List<String> getServiceNames() {
133        return serviceNames;
134    }
135
136    @Override
137    public String getComponentClass() {
138        return componentClass;
139    }
140
141    public void setComponentClass(String componentClass) {
142        this.componentClass = componentClass;
143    }
144
145    @Override
146    public boolean isXmlPureComponent() {
147        return componentClass == null;
148    }
149
150    @Override
151    public URL getXmlFileUrl() {
152        return xmlFileUrl;
153    }
154
155    public void setXmlFileUrl(URL xmlFileUrl) {
156        this.xmlFileUrl = xmlFileUrl;
157    }
158
159    @Override
160    public String getXmlFileName() {
161        if (xmlFileUrl == null) {
162            return "";
163        }
164        String path = xmlFileUrl.getPath();
165        String[] parts = path.split("!");
166        if (parts.length == 2) {
167            return parts[1];
168        } else {
169            return path;
170        }
171    }
172
173    @Override
174    public String getXmlFileContent() {
175        if (xmlFileUrl == null) {
176            return "";
177        }
178        String path = xmlFileUrl.getPath();
179        String[] parts = path.split("!");
180
181        File jar = new File(parts[0].replace("file:", ""));
182        if (!jar.exists()) {
183            return "Unable to locate Bundle :" + parts[0];
184        }
185
186        try {
187            String xml;
188            if (jar.getAbsolutePath().endsWith(".xml")) {
189                try (InputStream in = new FileInputStream(jar)) {
190                    xml = IOUtils.toString(in, StandardCharsets.UTF_8);
191                }
192            } else if (jar.isDirectory()) {
193                File file = new File(new Path(jar.getAbsolutePath()).append(parts[1]).toString());
194                if (!file.exists()) {
195                    return "Unable to locate file :" + file.getAbsolutePath();
196                }
197                xml = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
198            } else {
199                try (ZipFile jarArchive = new ZipFile(jar)) {
200                ZipEntry entry = jarArchive.getEntry(parts[1].substring(1));
201                    xml = IOUtils.toString(jarArchive.getInputStream(entry), StandardCharsets.UTF_8);
202                }
203            }
204            return DocumentationHelper.secureXML(xml);
205        } catch (IOException e) {
206            log.error("Error while getting XML file", e);
207            return "";
208        }
209    }
210
211    @Override
212    public String getId() {
213        return name;
214    }
215
216    @Override
217    public String getVersion() {
218        return bundle.getVersion();
219    }
220
221    @Override
222    public String getArtifactType() {
223        return TYPE_NAME;
224    }
225
226    @Override
227    public List<ServiceInfo> getServices() {
228        return services;
229    }
230
231    @Override
232    public String getHierarchyPath() {
233        return getBundle().getHierarchyPath() + "/" + getId();
234    }
235
236}