001/* 002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Stephane Lacoin at Nuxeo (aka matic) 016 */ 017package org.nuxeo.connect.tools.report; 018 019import java.io.IOException; 020import java.io.OutputStream; 021import java.net.Socket; 022import java.util.Arrays; 023import java.util.HashSet; 024import java.util.Iterator; 025import java.util.Set; 026 027import org.nuxeo.connect.tools.report.ReportConfiguration.Contribution; 028import org.nuxeo.ecm.core.management.statuses.NuxeoInstanceIdentifierHelper; 029import org.nuxeo.runtime.api.Framework; 030import org.nuxeo.runtime.management.ResourcePublisher; 031import org.nuxeo.runtime.model.ComponentContext; 032import org.nuxeo.runtime.model.ComponentInstance; 033import org.nuxeo.runtime.model.DefaultComponent; 034 035/** 036 * Reports aggregator, exposed as a service in the runtime. 037 * 038 * @since 8.3 039 */ 040public class ReportComponent extends DefaultComponent { 041 042 final ReportConfiguration configuration = new ReportConfiguration(); 043 044 final Service service = new Service(); 045 046 class Service implements ReportRunner { 047 048 public ReportConfiguration getConfiguration() { 049 return configuration; 050 } 051 052 @Override 053 public Set<String> list() { 054 Set<String> names = new HashSet<>(); 055 for (Contribution contrib : configuration) { 056 names.add(contrib.name); 057 } 058 return names; 059 } 060 061 @Override 062 public void run(OutputStream out, Set<String> names) throws IOException { 063 out.write('{'); 064 out.write('"'); 065 out.write(NuxeoInstanceIdentifierHelper.getServerInstanceName().getBytes()); 066 out.write('"'); 067 out.write(':'); 068 out.write('{'); 069 Iterator<Contribution> iterator = configuration.iterator(names); 070 while (iterator.hasNext()) { 071 Contribution contrib = iterator.next(); 072 out.write('"'); 073 out.write(contrib.name.getBytes()); 074 out.write('"'); 075 out.write(':'); 076 contrib.writer.write(out); 077 if (iterator.hasNext()) { 078 out.write(','); 079 } 080 out.flush(); 081 } 082 out.write('}'); 083 out.write('}'); 084 out.flush(); 085 } 086 } 087 088 final Management management = new Management(); 089 090 public class Management implements ReportServer { 091 092 @Override 093 public void run(String host, int port, String... names) throws IOException { 094 ClassLoader tcl = Thread.currentThread().getContextClassLoader(); 095 Thread.currentThread().setContextClassLoader(Management.class.getClassLoader()); 096 try (Socket sock = new Socket(host, port); OutputStream sink = sock.getOutputStream()) { 097 service.run(sink, new HashSet<>(Arrays.asList(names))); 098 } finally { 099 Thread.currentThread().setContextClassLoader(tcl); 100 } 101 } 102 103 } 104 105 @Override 106 public void start(ComponentContext context) { 107 Framework.getService(ResourcePublisher.class).registerResource("connect-report", "connect-report", ReportServer.class, management); 108 } 109 110 @Override 111 public void stop(ComponentContext context) { 112 Framework.getService(ResourcePublisher.class).unregisterResource("connect-report", "connect-report"); 113 } 114 115 116 @Override 117 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 118 if (contribution instanceof Contribution) { 119 configuration.addContribution((Contribution) contribution); 120 } else { 121 throw new IllegalArgumentException( 122 String.format("unknown contribution of type %s in %s", contribution.getClass(), contributor)); 123 } 124 } 125 126 @Override 127 public <T> T getAdapter(Class<T> adapter) { 128 if (adapter.isAssignableFrom(Service.class)) { 129 return adapter.cast(service); 130 } 131 return super.getAdapter(adapter); 132 } 133 134}