/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.tools.target.platform.indexer.client; import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.liferay.portal.target.platform.indexer.Indexer; import com.liferay.portal.target.platform.indexer.TargetPlatformIndexerUtil; import com.liferay.portal.target.platform.indexer.internal.DefaultIndexValidator; import com.liferay.portal.target.platform.indexer.internal.LPKGIndexer; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * @author Shuyang Zhou */ public class TargetPlatformIndexerClient { public static void main(String[] args) throws Exception { String liferayHome = System.getProperty("liferay.home"); if (liferayHome == null) { System.err.println( "== -Dliferay.home must point to a valid directory"); return; } String portalLibDirName = System.getProperty("portal.lib.dir"); if (portalLibDirName == null) { System.err.println( "== -Dportal.lib.dir must point to a valid directory"); return; } BytesURLSupport.init(); String indexesFileName = System.getProperty( "indexes.file", liferayHome + "/osgi/" + Indexer.DIR_NAME_TARGET_PLATFORM + "/target-platform-indexes-" + System.currentTimeMillis() + ".zip"); long stopWaitTimeout = Long.parseLong( System.getProperty("stop.wait.timeout", "30000")); String moduleFrameworkStaticDirName = System.getProperty( "module.framework.static.dir", liferayHome.concat("/osgi/static")); String moduleFrameworkModulesDirName = System.getProperty( "module.framework.modules.dir", liferayHome.concat("/osgi/modules")); String moduleFrameworkPortalDirName = System.getProperty( "module.framework.portal.dir", liferayHome.concat("/osgi/portal")); String moduleFrameworkMarketplaceDir = System.getProperty( "module.framework.marketplace.dir", liferayHome.concat("/osgi/marketplace")); List<URI> uris = _index( indexesFileName, Arrays.asList(new File(portalLibDirName, "util-taglib.jar")), stopWaitTimeout, moduleFrameworkStaticDirName, moduleFrameworkModulesDirName, moduleFrameworkPortalDirName, moduleFrameworkMarketplaceDir); if (_validate(uris)) { String integrityPropertiesFileName = System.getProperty( "integrity.properties", liferayHome + "/osgi/" + Indexer.DIR_NAME_TARGET_PLATFORM + "/integrity.properties"); _updateIntegrityProperties( uris, Paths.get(integrityPropertiesFileName)); } } private static List<URI> _index( String indexesFileName, List<File> additionalJarFiles, long stopWaitTimeout, String moduleFrameworkStaticDirName, String moduleFrameworkModulesDirName, String moduleFrameworkPortalDirName, String moduleFrameworkMarketplaceDirName) throws Exception { Path indexesFilePath = Paths.get(indexesFileName); if (Files.exists(indexesFilePath)) { return _loadIndexes(indexesFilePath); } List<URI> uris = new ArrayList<>(); uris.add( _indexTargetPlatform( additionalJarFiles, stopWaitTimeout, moduleFrameworkStaticDirName, moduleFrameworkModulesDirName, moduleFrameworkPortalDirName)); uris.addAll( _indexLPKGFiles( Utilities.listFiles( moduleFrameworkMarketplaceDirName, "*.lpkg"))); _saveIndexes(indexesFileName, uris); return uris; } private static List<URI> _indexLPKGFiles(List<File> lpkgFiles) throws Exception { List<URI> uris = new ArrayList<>(lpkgFiles.size()); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); for (File lpkgFile : lpkgFiles) { LPKGIndexer lpkgIndexer = new LPKGIndexer( lpkgFile, Collections.<String>emptySet()); lpkgIndexer.index(byteArrayOutputStream); String name = lpkgFile.getName(); byte[] bytes = byteArrayOutputStream.toByteArray(); URL url = BytesURLSupport.putBytes( name.substring(0, name.length() - 5), bytes); _writeIndexToLPKG(lpkgFile, bytes); byteArrayOutputStream.reset(); uris.add(url.toURI()); } return uris; } private static URI _indexTargetPlatform( List<File> additionalJarFiles, long stopWaitTimeout, String... dirNames) throws Exception { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); TargetPlatformIndexerUtil.indexTargetPlatform( byteArrayOutputStream, additionalJarFiles, stopWaitTimeout, dirNames); URL url = BytesURLSupport.putBytes( "liferay-target-platform", byteArrayOutputStream.toByteArray()); return url.toURI(); } private static List<URI> _loadIndexes(Path indexesFilePath) throws IOException { final List<URI> uris = new ArrayList<>(); try (FileSystem fileSystem = FileSystems.newFileSystem( indexesFilePath, null)) { for (Path rootPath : fileSystem.getRootDirectories()) { Files.walkFileTree( rootPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile( Path filePath, BasicFileAttributes basicFileAttributes) throws IOException { Path fileNamePath = filePath.getFileName(); String fileName = fileNamePath.toString(); if (!fileName.endsWith(".xml")) { return FileVisitResult.CONTINUE; } URL url = BytesURLSupport.putBytes( fileName.substring(0, fileName.length() - 4), Files.readAllBytes(filePath)); try { uris.add(url.toURI()); } catch (URISyntaxException urise) { throw new RuntimeException(urise); } return super.visitFile( filePath, basicFileAttributes); } }); } } return uris; } private static void _saveIndexes(String indexesFileName, List<URI> uris) throws IOException { Path path = Paths.get(indexesFileName); Files.createDirectories(path.getParent()); URI indexesURI = path.toUri(); try (FileSystem fileSystem = FileSystems.newFileSystem( URI.create("jar:file:" + indexesURI.getPath()), Collections.singletonMap("create", "true"))) { for (URI uri : uris) { URL url = uri.toURL(); String name = url.getFile(); int index = name.lastIndexOf('/'); if (index != -1) { name = name.substring(index + 1); } index = name.lastIndexOf('.'); if (index != -1) { name = name.substring(0, index); } name = URLDecoder.decode(name, "UTF-8"); try (InputStream inputStream = url.openStream()) { Files.copy( inputStream, fileSystem.getPath(name.concat(".xml")), StandardCopyOption.REPLACE_EXISTING); } } } System.out.println("== Saved indexes file at " + indexesFileName); } private static void _updateIntegrityProperties( List<URI> uris, Path integrityPropertiesPath) throws Exception { Collections.sort(uris); StringBuilder sb = new StringBuilder(); for (URI uri : uris) { sb.append(Utilities.toIntegrityKey(uri)); sb.append('='); sb.append(Utilities.toChecksum(uri)); sb.append('\n'); } sb.setLength(sb.length() - 1); Files.createDirectories(integrityPropertiesPath.getParent()); Files.write( integrityPropertiesPath, Collections.singleton(sb.toString()), StandardCharsets.UTF_8); System.out.println( "== Saved integrity.properties at " + integrityPropertiesPath); } private static boolean _validate(List<URI> uris) throws Exception { DefaultIndexValidator defaultIndexValidator = new DefaultIndexValidator( Collections.<URI>emptyList()); long start = System.currentTimeMillis(); try { List<String> messages = defaultIndexValidator.validate(uris); if (!messages.isEmpty()) { System.out.println("== Validation errors"); for (String message : messages) { System.out.println("== " + message); } return false; } System.out.println("== Successfully validated"); return true; } finally { long duration = System.currentTimeMillis() - start; System.out.printf( "== Time %02d:%02ds\n", MILLISECONDS.toMinutes(duration), MILLISECONDS.toSeconds(duration % 60000)); } } private static void _writeIndexToLPKG(File lpkg, byte[] bytes) throws IOException { try (FileSystem fileSystem = FileSystems.newFileSystem( lpkg.toPath(), null)) { // Specifying StandardOpenOption list is a workaround for a bug in // com.sun.nio.zipfs.ZipFileSystemProvider#newOutputStream( // Path, OpenOption...) that does not follow the API contract // specified in java.nio.file.Files#write(Path, byte[], // OpenOption...) to automatically add the StandardOpenOption list Files.write( fileSystem.getPath("index.xml"), bytes, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE); } } }