/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed 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 com.fujitsu.dc.engine.source; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.io.Charsets; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.fujitsu.dc.engine.DcEngineException; /** * Service resource source management using file system. */ public class FsServiceResourceSourceManager implements ISourceManager { /** ログオブジェクト. */ private static Logger log = LoggerFactory.getLogger(FsServiceResourceSourceManager.class); private String fsPath; /** コレクションのPROPPATCH情報. */ private String serviceCollectionInfo; /** Mapping from path to source file. */ private Map<String, String> pathMap = new HashMap<>(); private String serviceSubject; /** * コンストラクタ. * @param filePath 対象サービスコレクションのFile System Path. * @throws DcEngineException DcEngineException */ public FsServiceResourceSourceManager(String filePath) throws DcEngineException { this.fsPath = filePath; log.info("Source File Path: [" + this.fsPath + "]"); this.loadServiceCollectionInfo(); this.parseServiceTag(); } /** * サービスコレクションの情報を取得. * @throws DcEngineException DcEngineException */ private void loadServiceCollectionInfo() throws DcEngineException { // filePath null check. if (this.fsPath == null) { log.info("File path is empty."); throw new DcEngineException("404 Not Found (Request Header invalid) ", DcEngineException.STATUSCODE_NOTFOUND); } // サービスコレクションを取得 File metaFile = new File(this.fsPath + "/.pmeta"); JSONObject json = null; try (Reader reader = Files.newBufferedReader(metaFile.toPath(), Charsets.UTF_8)) { JSONParser parser = new JSONParser(); json = (JSONObject) parser.parse(reader); } catch (IOException | ParseException e) { // IO failure or JSON is broken log.info("Meta file not found or invalid (" + this.fsPath + ")"); throw new DcEngineException("500 Server Error", DcEngineException.STATUSCODE_SERVER_ERROR); } // スクリプトの情報を取得する this.serviceCollectionInfo = (String) ((Map<?, ?>) json.get("d")).get("service@urn:x-dc1:xmlns"); if (null == this.serviceCollectionInfo) { log.info("Service property Invalid "); throw new DcEngineException("404 Not Found (Service property invalid) ", DcEngineException.STATUSCODE_NOTFOUND); } log.debug("scriptPath: [" + this.serviceCollectionInfo + "] "); } /** * サービス名に対応したスクリプトファイル名の取得. * @param servicePath サービス名 * @return スクリプトファイル名 */ public String getScriptNameForServicePath(String servicePath) { return this.pathMap.get(servicePath); } /** * ソースファイルを取得. * @param sourceName ソースファイル名 * @return ソースファイルの中身 * @throws DcEngineException DcEngineException */ public String getSource(String sourceName) throws DcEngineException { // 対象のスクリプトの情報を取得する String sourcePath = this.fsPath + File.separator + "__src" + File.separator + sourceName + File.separator + "content"; File sourceFile = new File(sourcePath); if (!sourceFile.exists()) { log.info("Service Source not found (" + sourceName + ")"); throw new DcEngineException("404 Not Found", DcEngineException.STATUSCODE_NOTFOUND); } try { return new String(Files.readAllBytes(sourceFile.toPath()), Charsets.UTF_8); } catch (IOException e) { log.info("UserScript Encoding error(UnsupportedEncodingException) ", e); throw new DcEngineException("404 UserScript Encoding error", DcEngineException.STATUSCODE_NOTFOUND, e); } } /** * サービスコレクションに設定されたサービスサブジェクトの取得. * @return サービスサブジェクト */ public String getServiceSubject() { return this.serviceSubject; } /** * サービス名からスクリプトファイルのパスを取得する. * @param xml XML文字列 * @param svcName サービス名 * @return スクリプトファイルパス */ private void parseServiceTag() { DocumentBuilder builder = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = null; InputStream is = new ByteArrayInputStream(this.serviceCollectionInfo.getBytes()); try { doc = builder.parse(is); Element el = doc.getDocumentElement(); this.serviceSubject = el.getAttribute("subject"); NodeList nl = doc.getElementsByTagNameNS("*", "path"); for (int i = 0; i < nl.getLength(); i++) { NamedNodeMap nnm = nl.item(i).getAttributes(); pathMap.put(nnm.getNamedItem("name").getNodeValue(),nnm.getNamedItem("src").getNodeValue()); } } catch (SAXException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } }