zhoushihao
2 天以前 4e3b8155722b66e25df3c6fd42cc586b68dea391
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package com.kangaroohy.milo.pool;
 
import com.kangaroohy.milo.configuration.MiloProperties;
import com.kangaroohy.milo.exception.EndPointNotFoundException;
import com.kangaroohy.milo.exception.IdentityNotFoundException;
import com.kangaroohy.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
 
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
 
/**
 * 类 MiloConnectFactory 功能描述:<br/>
 *
 * @author mes
 * @version 0.0.1
 * @date 2023/5/4 18:56
 */
@Slf4j
public class MiloConnectFactory implements KeyedPooledObjectFactory<MiloProperties.Config, OpcUaClient> {
 
    public MiloConnectFactory(MiloProperties properties) {
        CustomUtil.verifyProperties(properties);
    }
 
    /**
     * 创建对象
     *
     * @return
     * @throws Exception
     */
    @Override
    public PooledObject<OpcUaClient> makeObject(MiloProperties.Config key) throws Exception {
        OpcUaClient client = null;
        try {
            client = createClient(key);
            client.connect().get();
            return new DefaultPooledObject<>(client);
        } catch (Exception e) {
            if (client != null) {
                client.disconnect().get();
            }
            throw new InterruptedException(e.getMessage());
        }
    }
 
    /**
     * 对象要被销毁时(validateObject方法返回false或者超时)后被调用
     *
     * @param pooledObject
     * @throws Exception
     */
    @Override
    public void destroyObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
        OpcUaClient opcUaClient = pooledObject.getObject();
        log.info("disconnect opcUaClient {}", opcUaClient.getConfig().getApplicationName().getText());
        opcUaClient.disconnect().get();
    }
 
    /**
     * 每次获取对象和还回对象时会被调用,如果返回false会销毁对象
     */
    @Override
    public boolean validateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) {
        return true;
    }
 
    /**
     * 调用获取对象方法前被调用
     * 此方法一般进行一些前置操作
     */
    @Override
    public void activateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
 
    }
 
    /**
     * 当还回对象并且validateObject方法返回true后被调用
     * 一般在此方法中对刚刚使用完成的对象进行重置
     */
    @Override
    public void passivateObject(MiloProperties.Config key, PooledObject<OpcUaClient> pooledObject) throws Exception {
 
    }
 
    private OpcUaClient createClient(MiloProperties.Config key) throws Exception {
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }
        return OpcUaClient.create(key.getEndpoint(),
                endpoints -> {
                    final Optional<EndpointDescription> endpoint = endpoints
                            .stream()
//                            .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                            .findFirst();
                    EndpointDescription newEndpoint = new EndpointDescription(key.getEndpoint(), endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                            endpoint.get().getSecurityMode(), endpoint.get().getSecurityPolicyUri(), endpoint.get().getUserIdentityTokens(),
                            endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                    return Optional.of(newEndpoint);
                },
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
                                .setApplicationUri("urn:eclipse:milo:examples:client")
                                //访问方式
                                .setIdentityProvider(new UsernameProvider(key.getUsername(), key.getPassword()))
                                .setRequestTimeout(UInteger.valueOf(5000))
                                .build()
        );
    }
 
    private URI getUri(MiloProperties.Config key) {
        try {
            return new URI(endpointUrl(key));
        } catch (URISyntaxException e) {
            throw new EndPointNotFoundException("endpoint 配置异常");
        }
    }
 
    private String endpointUrl(MiloProperties.Config key) {
        return key.getEndpoint();
    }
 
    private SecurityPolicy securityPolicy(MiloProperties.Config key) {
        return key.getSecurityPolicy();
    }
 
    private IdentityProvider identityProvider(MiloProperties.Config key) {
        if (securityPolicy(key).equals(SecurityPolicy.None)) {
            return new AnonymousProvider();
        }
        if (key.getUsername() == null || key.getPassword() == null) {
            throw new IdentityNotFoundException("连接信息未完善");
        } else {
            return new UsernameProvider(key.getUsername(), key.getPassword());
        }
    }
}