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.time.Instant; 023import java.util.Arrays; 024import java.util.HashSet; 025import java.util.Iterator; 026import java.util.Set; 027 028import org.nuxeo.connect.tools.report.ReportConfiguration.Contribution; 029import org.nuxeo.ecm.core.management.statuses.NuxeoInstanceIdentifierHelper; 030import org.nuxeo.runtime.api.Framework; 031import org.nuxeo.runtime.management.ResourcePublisher; 032import org.nuxeo.runtime.model.ComponentContext; 033import org.nuxeo.runtime.model.ComponentInstance; 034import org.nuxeo.runtime.model.DefaultComponent; 035 036/** 037 * Reports aggregator, exposed as a service in the runtime. 038 * 039 * @since 8.3 040 */ 041public class ReportComponent extends DefaultComponent { 042 043 public static ReportComponent instance; 044 045 public ReportComponent() { 046 instance = this; 047 } 048 049 final ReportConfiguration configuration = new ReportConfiguration(); 050 051 final Service service = new Service(); 052 053 class Service implements ReportRunner { 054 @Override 055 public Set<String> list() { 056 Set<String> names = new HashSet<>(); 057 for (Contribution contrib : configuration) { 058 names.add(contrib.name); 059 } 060 return names; 061 } 062 063 @Override 064 public void run(OutputStream out, Set<String> names) throws IOException { 065 out.write('{'); 066 out.write('"'); 067 out.write(NuxeoInstanceIdentifierHelper.getServerInstanceName().getBytes()); 068 out.write('"'); 069 out.write(':'); 070 out.write('{'); 071 Iterator<Contribution> iterator = configuration.iterator(names); 072 while (iterator.hasNext()) { 073 Contribution contrib = iterator.next(); 074 out.write('"'); 075 out.write(contrib.name.getBytes()); 076 out.write('"'); 077 out.write(':'); 078 contrib.writer.write(out); 079 if (iterator.hasNext()) { 080 out.write(','); 081 } 082 out.flush(); 083 } 084 out.write('}'); 085 out.write('}'); 086 out.flush(); 087 } 088 } 089 090 final Management management = new Management(); 091 092 public class Management implements ReportServer { 093 094 @Override 095 public void run(String host, int port, String... names) throws IOException { 096 ClassLoader tcl = Thread.currentThread().getContextClassLoader(); 097 Thread.currentThread().setContextClassLoader(Management.class.getClassLoader()); 098 try (Socket sock = new Socket(host, port); OutputStream sink = sock.getOutputStream()) { 099 service.run(sink, new HashSet<>(Arrays.asList(names))); 100 } finally { 101 Thread.currentThread().setContextClassLoader(tcl); 102 } 103 } 104 105 } 106 107 @Override 108 public void start(ComponentContext context) { 109 Framework.getService(ResourcePublisher.class).registerResource("connect-report", "connect-report", ReportServer.class, management); 110 } 111 112 @Override 113 public void stop(ComponentContext context) { 114 Framework.getService(ResourcePublisher.class).unregisterResource("connect-report", "connect-report"); 115 } 116 117 118 @Override 119 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 120 if (contribution instanceof Contribution) { 121 configuration.addContribution((Contribution) contribution); 122 } else { 123 throw new IllegalArgumentException( 124 String.format("unknown contribution of type %s in %s", contribution.getClass(), contributor)); 125 } 126 } 127 128 @Override 129 public <T> T getAdapter(Class<T> adapter) { 130 if (adapter.isAssignableFrom(Service.class)) { 131 return adapter.cast(service); 132 } 133 return super.getAdapter(adapter); 134 } 135 136}