├── jpost
├── .gitignore
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── mindorks
│ │ └── jpost
│ │ ├── core
│ │ ├── ChannelType.java
│ │ ├── ChannelState.java
│ │ ├── OnMessage.java
│ │ ├── CustomChannel.java
│ │ ├── PrivateChannel.java
│ │ ├── Post.java
│ │ ├── AbstractChannel.java
│ │ ├── Channel.java
│ │ ├── ChannelPost.java
│ │ ├── PublicChannel.java
│ │ ├── DefaultChannel.java
│ │ ├── BroadcastCenter.java
│ │ ├── Broadcast.java
│ │ └── AbstractBroadcastCenter.java
│ │ └── exceptions
│ │ ├── NullObjectException.java
│ │ ├── PermissionException.java
│ │ ├── AlreadyExistsException.java
│ │ ├── NoSuchChannelException.java
│ │ ├── JPostNotRunningException.java
│ │ ├── InvalidSubscriberException.java
│ │ └── IllegalChannelStateException.java
└── build.gradle
├── android-jpost
├── .gitignore
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── mindorks
│ │ └── androidjpost
│ │ ├── droid
│ │ ├── OnUiThread.java
│ │ ├── AndroidPublicChannel.java
│ │ ├── AndroidDefaultChannel.java
│ │ └── AndroidPrivateChannel.java
│ │ ├── JPost.java
│ │ └── AndroidBroadcastCenter.java
└── build.gradle
├── java-jpost
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── mindorks
│ └── javajpost
│ └── JPost.java
├── .gitignore
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .travis.yml
├── src
└── main
│ └── java
│ └── tes
│ └── mindorks
│ └── jpost
│ ├── ChannelIds.java
│ ├── message
│ ├── Message1.java
│ └── Message2.java
│ ├── Application.java
│ ├── subscriber
│ ├── SubscriberAsync.java
│ └── Subscriber.java
│ ├── TestDefaultChannel.java
│ ├── TestPublicChannel.java
│ └── TestPrivateChannel.java
├── gradlew.bat
├── gradlew
├── LICENSE
└── README.md
/jpost/.gitignore:
--------------------------------------------------------------------------------
1 | build
--------------------------------------------------------------------------------
/android-jpost/.gitignore:
--------------------------------------------------------------------------------
1 | build
--------------------------------------------------------------------------------
/java-jpost/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | .gradle
3 | .idea
4 | local.properties
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'JPost'
2 | include ':jpost', ':android-jpost', ':java-jpost'
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/janishar/JPost/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | script:
4 | gradle check
5 |
6 | jdk:
7 | - oraclejdk8
8 | - oraclejdk7
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 21 22:37:27 IST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip
7 |
--------------------------------------------------------------------------------
/src/main/java/tes/mindorks/jpost/ChannelIds.java:
--------------------------------------------------------------------------------
1 | package tes.mindorks.jpost;
2 |
3 | /**
4 | * Created by janisharali on 24/09/16.
5 | */
6 | public class ChannelIds {
7 |
8 | public static final int publicChannel1 = 1;
9 | public static final int privateChannel1 = 2;
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/tes/mindorks/jpost/message/Message1.java:
--------------------------------------------------------------------------------
1 | package tes.mindorks.jpost.message;
2 |
3 | /**
4 | * Created by janisharali on 24/09/16.
5 | */
6 | public class Message1 {
7 |
8 | private String msg;
9 |
10 | public Message1(String msg) {
11 | this.msg = msg;
12 | }
13 |
14 | public String getMsg() {
15 | return "Message1: " + msg;
16 | }
17 |
18 | public void setMsg(String msg) {
19 | this.msg = msg;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/tes/mindorks/jpost/message/Message2.java:
--------------------------------------------------------------------------------
1 | package tes.mindorks.jpost.message;
2 |
3 | /**
4 | * Created by janisharali on 24/09/16.
5 | */
6 | public class Message2 {
7 |
8 | private String msg;
9 |
10 | public Message2(String msg) {
11 | this.msg = msg;
12 | }
13 |
14 | public String getMsg() {
15 | return "Message2: " + msg;
16 | }
17 |
18 | public void setMsg(String msg) {
19 | this.msg = msg;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/ChannelType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public enum ChannelType {
23 | DEFAULT, PUBLIC, PRIVATE;
24 | }
25 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/ChannelState.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public enum ChannelState {
23 | OPEN, STOPPED, TERMINATED;
24 | }
25 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/NullObjectException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class NullObjectException extends Exception{
23 |
24 | public NullObjectException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "NullObjectException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/PermissionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class PermissionException extends Exception{
23 |
24 | public PermissionException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "PermissionException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/AlreadyExistsException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class AlreadyExistsException extends Exception{
23 |
24 | public AlreadyExistsException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "AlreadyExistsException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/NoSuchChannelException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class NoSuchChannelException extends Exception{
23 |
24 | public NoSuchChannelException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "NoSuchChannelException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/android-jpost/src/main/java/com/mindorks/androidjpost/droid/OnUiThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.androidjpost.droid;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | /**
25 | * Created by janisharali on 26/09/16.
26 | */
27 | @Retention(RetentionPolicy.RUNTIME)
28 | @Target(ElementType.METHOD)
29 | public @interface OnUiThread {
30 | }
31 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/JPostNotRunningException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class JPostNotRunningException extends Exception{
23 |
24 | public JPostNotRunningException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "JPostNotRunningException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/InvalidSubscriberException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class InvalidSubscriberException extends Exception{
23 |
24 | public InvalidSubscriberException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "InvalidSubscriberException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/exceptions/IllegalChannelStateException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.exceptions;
18 |
19 | /**
20 | * Created by janisharali on 22/09/16.
21 | */
22 | public class IllegalChannelStateException extends Exception{
23 |
24 | public IllegalChannelStateException(String message) {
25 | super(message);
26 | }
27 |
28 | public String toString() {
29 | return "IllegalChannelStateException[" + super.getMessage() + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/OnMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | import com.mindorks.jpost.core.Channel;
20 |
21 | import java.lang.annotation.ElementType;
22 | import java.lang.annotation.Retention;
23 | import java.lang.annotation.RetentionPolicy;
24 | import java.lang.annotation.Target;
25 |
26 | /**
27 | * Created by janisharali on 23/09/16.
28 | */
29 | @Retention(RetentionPolicy.RUNTIME)
30 | @Target(ElementType.METHOD)
31 | public @interface OnMessage {
32 | int channelId() default Channel.DEFAULT_CHANNEL_ID;
33 | boolean isCommonReceiver() default false;
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/tes/mindorks/jpost/Application.java:
--------------------------------------------------------------------------------
1 | package tes.mindorks.jpost;
2 |
3 | import com.mindorks.javajpost.JPost;
4 |
5 | /**
6 | * Created by janisharali on 30/09/16.
7 | */
8 |
9 | public class Application {
10 |
11 | public static void main(String[] args){
12 | System.out.println(".......................DEFAULT CHANNEL TEST START..............................");
13 | TestDefaultChannel.test();
14 | try {
15 | Thread.sleep(3000);
16 | System.out.println(".......................DEFAULT CHANNEL TEST END..............................");
17 | JPost.shutdown();
18 | }catch (InterruptedException e){
19 | e.printStackTrace();
20 | }
21 |
22 | System.out.println(".......................PUBLIC CHANNEL TEST START..............................");
23 | TestPublicChannel.test();
24 | try {
25 | Thread.sleep(3000);
26 | System.out.println(".......................PUBLIC CHANNEL TEST END..............................");
27 | JPost.shutdown();
28 | }catch (InterruptedException e){
29 | e.printStackTrace();
30 | }
31 |
32 | System.out.println(".......................PRIVATE CHANNEL TEST START..............................");
33 | TestPrivateChannel.test();
34 | try {
35 | Thread.sleep(3000);
36 | System.out.println(".......................PRIVATE CHANNEL TEST END..............................");
37 | JPost.shutdown();
38 | }catch (InterruptedException e){
39 | e.printStackTrace();
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/CustomChannel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | import com.mindorks.jpost.exceptions.IllegalChannelStateException;
20 | import com.mindorks.jpost.exceptions.NullObjectException;
21 |
22 | import java.lang.ref.WeakReference;
23 | import java.util.concurrent.ConcurrentHashMap;
24 | import java.util.concurrent.PriorityBlockingQueue;
25 |
26 | /**
27 | * Created by janisharali on 22/09/16.
28 | */
29 | public interface CustomChannel>,
30 | M extends ConcurrentHashMap extends Integer,? extends WeakReference>>>
31 | extends Channel{
32 |
33 |
34 | void terminateChannel();
35 |
36 | void startChannel();
37 |
38 | void stopChannel();
39 |
40 | /**
41 | *
42 | * @param msg
43 | * @param subscriberIds
44 | * @param
45 | * @throws NullObjectException
46 | * @throws IllegalChannelStateException
47 | */
48 | void broadcast(T msg, Integer... subscriberIds) throws NullObjectException, IllegalChannelStateException;
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/tes/mindorks/jpost/subscriber/SubscriberAsync.java:
--------------------------------------------------------------------------------
1 | package tes.mindorks.jpost.subscriber;
2 |
3 |
4 | import com.mindorks.javajpost.JPost;
5 | import com.mindorks.jpost.core.OnMessage;
6 |
7 | import tes.mindorks.jpost.ChannelIds;
8 | import tes.mindorks.jpost.message.Message1;
9 | import tes.mindorks.jpost.message.Message2;
10 |
11 | /**
12 | * Created by janisharali on 24/09/16.
13 | */
14 | public class SubscriberAsync {
15 |
16 | private char classifier;
17 | public SubscriberAsync(char classifier) {
18 | this.classifier = classifier;
19 | JPost.getBroadcastCenter().addSubscriberAsync(this);
20 | }
21 |
22 | public SubscriberAsync(char classifier, int channelId) {
23 | this.classifier = classifier;
24 | JPost.getBroadcastCenter().addSubscriberAsync(channelId, this);
25 | }
26 |
27 | public SubscriberAsync(char classifier, int channelId, int subscriberId) {
28 | this.classifier = classifier;
29 | JPost.getBroadcastCenter().addSubscriberAsync(channelId, this, subscriberId);
30 | }
31 |
32 | public SubscriberAsync(T owner, char classifier, int channelId, int subscriberId) {
33 | this.classifier = classifier;
34 | try {
35 | JPost.getBroadcastCenter().addSubscriberAsync(owner, channelId, this, subscriberId);
36 | }catch (Exception e){
37 | e.printStackTrace();
38 | }
39 | }
40 |
41 | public void subscribeAsync(){
42 | JPost.getBroadcastCenter().addSubscriberAsync(this);
43 | }
44 |
45 |
46 | @OnMessage
47 | private void onMessage1(Message1 msg){
48 | System.out.println("SubscriberAsync" + classifier + ": "+ msg.getMsg());
49 | }
50 |
51 | @OnMessage(channelId = ChannelIds.publicChannel1)
52 | private void onMessage1Pub(Message1 msg){
53 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg());
54 | }
55 |
56 | @OnMessage(channelId = ChannelIds.privateChannel1)
57 | private void onMessage1Pri(Message1 msg){
58 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg());
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/PrivateChannel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | import com.mindorks.jpost.exceptions.InvalidSubscriberException;
20 | import com.mindorks.jpost.exceptions.NullObjectException;
21 |
22 | import java.lang.ref.WeakReference;
23 | import java.util.concurrent.ConcurrentHashMap;
24 | import java.util.concurrent.PriorityBlockingQueue;
25 |
26 | /**
27 | * Created by janisharali on 22/09/16.
28 | */
29 | public class PrivateChannel<
30 | Q extends PriorityBlockingQueue>,
31 | M extends ConcurrentHashMap>>
32 | extends PublicChannel{
33 |
34 | private WeakReference
26 |
27 |
28 |
29 |
30 |
Execution Model
31 |
32 |
33 |
34 |
35 |
36 | # About The Author
37 | You can connect with me here:
38 | * [Janishar Ali](https://janisharali.com)
39 | * [Twitter](https://twitter.com/janisharali)
40 | * [YouTube Channel](https://www.youtube.com/@unusualcode)
41 |
42 | ## If this library helps you in anyway, show your love :heart: by putting a :star: on this project :v:
43 |
44 | # Gradle
45 | # Java
46 | ```groovy
47 | dependencies {
48 | compile 'com.mindorks:java-jpost:0.0.4'
49 | }
50 | ```
51 | # Android
52 | ```groovy
53 | dependencies {
54 | compile 'com.mindorks:android-jpost:0.0.4'
55 | }
56 | ```
57 |
58 | # Why should you use this library
59 | 1. In contrast to the existing pub-sub libraries, it hold the subscribers with weakreference. Thus it doesn't create memory leaks.
60 | 2. Single message can be sent to selected subscribes. This avoids the problem of event getting received at undesirable places. Thus minimising the chances of abnormal application behaviour.
61 | 3. The subscriber addition can be controlled by using private channels. It minimises the chances of adding subscribes by mistake to receive undesirable messages.
62 | 4. It is a tiny library < 55kb . Thus not effecting the application overall size.
63 | 5. It facilitates synchronous as well as asynchronous message delivery and processing.
64 | 6. It provides a mechanism to run code asynchronously.
65 |
66 | # Library Classes Overview
67 | # `JPost`
68 | ### The one point entry for this library is the class `JPost`. It contains static methods to access `BroadcastCenter` class and core functionality related to the library management.
69 | ## Methods
70 | 1. `JPost.getBroadcastCenter()`: This method is used to get the instance of BroadcastCenter class (BroadcastCenter is described below)
71 | 2. `JPost.shutdown()`: This method closes the `JPost` for the async operations and removes all the pool threads. It should called when the program terminates or as required. This call let the message delivery already in process to continue.
72 | 3. `JPost.haltAndShutdown()`: This method does the same operation as do the `JPost.shutdown()` but it also removes all the message delivery tasks.;
73 |
74 |
75 |
76 | # `BroadcastCenter`
77 | ### This class proivdes all the functionality attached with this library.
78 | ## Methods
79 | 1. `createPrivateChannel(T owner, Integer channelId)`: Creates a private channel requiring a unique int channel id. The owner is assigned `owner.hashCode()` as subscriber id.
80 | 2. `createPrivateChannel(T owner, Integer channelId, Integer subscriberId)`: Creates a private channel requiring a unique int channel id. The owner is given `subscriberId` as subscriber id.
81 | 3. `createPublicChannel(Integer channelId)`: Creates a public channel requiring a unique int channel id.
82 | 4. `stopChannel(Integer channelId)`: Stops the channel with channel id temporarily.
83 | 5. `reopenChannel(Integer channelId)`: Reopen the channel which has been stopped but not terminated.
84 | 6. `terminateChannel(Integer channelId)`: Completely removes the channel and can not be used later.
85 | 7. `getChannel(Integer channelId)`: Return the channel with channel id else returns null.
86 | 8. `broadcast(T msg)`: This method sends messages to all the subscribers of the default global channel.
87 | 9. `broadcastAsync(T msg)`: This method sends messages asynchronously to all the subscribers of the default global channel. The thread calling this methods can process with remaining tasks as usual.
88 | 10. `broadcast(Integer channelId, T msg, Integer... subscribers)`: This method sends messages to the subscribers of the channel of a particular channel id. If subscribers is not provided then all the subscribers of this channel receiver the message.
89 | 11. `broadcastAsync(Integer channelId, T msg, Integer... subscribers)`: Does the same as above(method 10) but asynchronously.
90 | 12. `broadcast(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)`: This method is used to send message on a private channel. Only the registered subscribers can send and receive messges on private channel.
91 | 13. `broadcastAsync(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)`: Does the same as above(method 12) but asynchronously.
92 | 14. `addSubscriber(T subscriber)`: This method add subscribers to default global channel.
93 | 15. `addSubscriber(Integer channelId, T subscriber)`: This method add subscribers to public channels with subscriber having `subscriber.hashCode()` as the subscriber id.
94 | 16. `addSubscriberAsync(Integer channelId, T subscriber)`: Does the same as above(method 15) but asynchronously.
95 | 17. `addSubscriber(Integer channelId, T subscriber, Integer subscriberId)`: This method add subscribers to public channels with subscriber having `subscriberId` as the subscriber id.
96 | 18. `addSubscriberAsync(Integer channelId, T subscriber, Integer subscriberId)`: Does the same as above(method 17) but asynchronously.
97 | 19. `addSubscriber(V owner, Integer channelId, T subscriber)`: This method add subscribers to private channels. Only owner of the channel can add subscribers to this channel. The subscriber is given subscriber.hashCode() as the subscriber id.
98 | 20. `addSubscriberAsync(V owner, Integer channelId, T subscriber)`: Does the same as above(method 19) but asynchronously.
99 | 21. `addSubscriber(V owner, Integer channelId, T subscriber, Integer subscriberId)`: This method add subscribers to private channels. Only owner of the channel can add subscribers to this channel. The subscriber is given `subscriberId` as the subscriber id.
100 | 22. `addSubscriberAsync(V owner, Integer channelId, T subscriber, Integer subscriberId)`: Does the same as above(method 21) but asynchronously.
101 | 23. `removeSubscriber(T subscriber)`: Removes subscriber form the default global channel.
102 | 24. `removeSubscriber(Integer channelId, T subscriber)`: Removes subscriber form a public channel.
103 | 25. `removeSubscriber(T registeredSubscriber, Integer channelId, Integer subscriberId)`: Removes subscriber form a private channel. Only registered subscribers of the private channel can remove a subscriber.
104 | 26. `getAllSubscribersWeakRef()`: returns a collection of weakreference holding the subscriber.
105 |
106 |
107 |
108 | # Receiving Messages
109 | ### The messages are received via `@OnMessage` method annotation. The class subscribing any message has to create a method with message object as the parameter and annotate it with `@OnMessage`.
110 |
111 | ### `@OnMessage` Parameters
112 | 1. `channelId`: This parameter in the annotation, attaches the message reception to a particular channel on which the class has subscribed. If not provided will be listening to the default global channel.
113 | 2. `isCommonReceiver`: This parameter sets the message reception from any channel on which the class has subscribed.
114 |
115 | # Android Note:
116 | ### `@OnUiThread` : This annotation run the code in UI / main thread
117 | ```java
118 | @OnUiThread
119 | @OnMessage
120 | private void onMessage(final Message msg){
121 | textView.setText(msg.getMsg());
122 | }
123 | ```
124 |
125 | # Proguard Note:
126 | ### If you are using proguard, then add this rule in proguard-project.txt
127 | ```groovy
128 | -keepattributes *Annotation*
129 | -keepclassmembers class ** {
130 | @com.mindorks.jpost.core.OnMessage ;
131 | @com.mindorks.androidjpost.droid.OnUiThread ;
132 | }
133 | ```
134 |
135 | ## Example 1: Sending and receiving messages over default global channel
136 |
137 | ### Step 1: Create a message class that will be passed on the channel for broadcasting.
138 |
139 | ```java
140 | public class Message1 {
141 |
142 | private String msg;
143 |
144 | public Message1(String msg) {
145 | this.msg = msg;
146 | }
147 |
148 | public String getMsg() {
149 | return "Message1: " + msg;
150 | }
151 |
152 | public void setMsg(String msg) {
153 | this.msg = msg;
154 | }
155 | }
156 | ```
157 | ### Step 2: Subscribe the class to the default global channel
158 | ### Step 3: Attach the message to a recipient class
159 |
160 | ```java
161 | public SubscriberA() {
162 | try {
163 | JPost.getBroadcastCenter().addSubscriber(this);
164 | }catch (AlreadyExistsException | NullObjectException e){
165 | e.printStackTrace();
166 | }
167 | }
168 |
169 | @OnMessage
170 | private void onMessage1(Message1 msg){
171 | System.out.println("SubscriberA: "+ msg.getMsg());
172 | }
173 | ```
174 |
175 | ### Step 4: Send the message to the class
176 | ```java
177 | //TO SEND THROUGH THE CLASS RUNNING THREAD USER
178 | JPost.getBroadcastCenter().broadcast(new Message1("Application sending message"));
179 |
180 | // TO SEND ASYNCHRONOUSLY
181 | try {
182 | JPost.getBroadcastCenter().broadcastAsync(new Message2("Application sending message"));
183 | }catch (JPostNotRunningException e){
184 | e.printStackTrace();
185 | }
186 | ```
187 |
188 | ## Example 2: Creating public channel and sending and receiving messages over it
189 |
190 | ### Step 1: Create Message class. This is same as above example 1.
191 |
192 | ### Step 2: Create a public channel and give it a unique id.
193 |
194 | ```java
195 | class ChannelIds{
196 | public static final int publicChannel1 = 1;
197 | }
198 |
199 | .....
200 | try {
201 | JPost.getBroadcastCenter().createPublicChannel(ChannelIds.publicChannel1);
202 | }catch (AlreadyExistsException e){
203 | e.printStackTrace();
204 | }
205 | ```
206 | ### Step 3: Subscribe and attach a message recipient to a class
207 | ```java
208 | public SubscriberA() {
209 | // TO ADD SUBSCRIBER SYNCHRONOUSLY
210 | try {
211 | JPost.getBroadcastCenter().addSubscriber(ChannelIds.publicChannel1, this);
212 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException
213 | | IllegalChannelStateException | NullObjectException e){
214 | e.printStackTrace();
215 | }
216 |
217 | ...
218 | // TO ADD SUBSCRIBER ASYNCHRONOUSLY
219 | // JPost.getBroadcastCenter().addSubscriberAsync(ChannelIds.publicChannel1, this);
220 | }
221 |
222 | @OnMessage(channelId = ChannelIds.publicChannel1)
223 | private void onMessage1(Message1 msg){
224 | System.out.println("SubscriberA: " + msg.getMsg());
225 | }
226 | ```
227 |
228 | ### Step 4: Send Message via public channel
229 | ```java
230 | //TO SEND THROUGH THE CLASS RUNNING THREAD USER
231 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, new Message1("Application sending public message"));
232 |
233 | // TO SEND ASYNCHRONOUSLY
234 | try {
235 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Application sending public async message"));
236 | }catch (JPostNotRunningException e){
237 | e.printStackTrace();
238 | }
239 | ```
240 |
241 | ## Example 3: Creating private channel, adding subscribers(Only creator/owner of the channel has adding subscribers right) and sending and receiving messages over it
242 | ```java
243 | public class ChannelIds {
244 | public static final int privateChannel1 = 2;
245 | }
246 |
247 | // CREATING PRIVATE CHANNEL
248 | try {
249 | JPost.getBroadcastCenter().createPrivateChannel(this, ChannelIds.privateChannel1);
250 | }catch (AlreadyExistsException e){
251 | e.printStackTrace();
252 | }
253 |
254 | // ADDING
255 | try {
256 | JPost.getBroadcastCenter().addSubscriber(this, ChannelIds.privateChannel1, subscriberA);
257 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException
258 | | IllegalChannelStateException | NullObjectException e){
259 | e.printStackTrace();
260 | }
261 |
262 | // SUBSCRIBING PRIVATE MESSAGES
263 | @OnMessage(channelId = ChannelIds.privateChannel1)
264 | private void onMessage1(Message1 msg){
265 | System.out.println("SubscriberD: " + msg.getMsg());
266 | }
267 |
268 | ```
269 |
270 | # Interesting Usage
271 | ### 1. The subscribers are added with unique ids. If id is not provided then its hashcode is taken as the id.
272 | ```java
273 | int subscriberId = 1;
274 | try {
275 | JPost.getBroadcastCenter().addSubscriber(ChannelIds.publicChannel1, this, subscriberId);
276 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException
277 | | IllegalChannelStateException | NullObjectException e){
278 | e.printStackTrace();
279 | }
280 | ```
281 | ### 2. The message can also be send to select subscribers on the channel
282 | ```java
283 | int subscriberId1 = 1;
284 | int subscriberId2 = 2;
285 | try {
286 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1,
287 | new Message1("Application sending public message"), subscriberId1, subscriberId2);
288 | }catch (JPostNotRunningException e){
289 | e.printStackTrace();
290 | }
291 | ```
292 | # Example
293 | [Android Networking](https://medium.com/@janishar.ali/android-networking-bare-skin-understanding-jpost-5be25f3df4d6#.q21wa4wmy)
294 |
295 |
296 | # Recent Library: [`PlaceHolderView`](https://github.com/janishar/PlaceHolderView)
297 | #### `PlaceHolderView` create views without any adapter in very modular form. It uses the power of RecyclerView and enhances it to another level. For the first time with the list view comes card stack view.
298 |
299 | # License
300 |
301 | ```
302 | Copyright (C) 2016 Janishar Ali Anwar
303 |
304 | Licensed under the Apache License, Version 2.0 (the "License");
305 | you may not use this file except in compliance with the License.
306 | You may obtain a copy of the License at
307 |
308 | http://www.apache.org/licenses/LICENSE-2.0
309 |
310 | Unless required by applicable law or agreed to in writing, software
311 | distributed under the License is distributed on an "AS IS" BASIS,
312 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
313 | See the License for the specific language governing permissions and
314 | limitations under the License
315 |
316 | ```
317 |
318 |
319 |
320 |
--------------------------------------------------------------------------------
/jpost/src/main/java/com/mindorks/jpost/core/AbstractBroadcastCenter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Janishar Ali Anwar
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License
15 | */
16 |
17 | package com.mindorks.jpost.core;
18 |
19 | import com.mindorks.jpost.exceptions.*;
20 |
21 | import java.lang.ref.WeakReference;
22 | import java.util.Collection;
23 | import java.util.concurrent.ConcurrentHashMap;
24 | import java.util.concurrent.ExecutorService;
25 | import java.util.concurrent.PriorityBlockingQueue;
26 | import java.util.concurrent.locks.ReentrantLock;
27 |
28 |
29 | /**
30 | * Created by janisharali on 22/09/16.
31 | */
32 | public abstract class AbstractBroadcastCenter
33 | implements Broadcast>,
34 | ConcurrentHashMap>>>{
35 |
36 | private ReentrantLock channelStateChangerLock;
37 | private ConcurrentHashMap>,
38 | ConcurrentHashMap>>> channelMap;
39 | private ExecutorService executorService;
40 |
41 | public AbstractBroadcastCenter(ConcurrentHashMap>,
42 | ConcurrentHashMap>>> channelMap, ExecutorService executorService) {
43 | this.channelMap = channelMap;
44 | this.executorService = executorService;
45 | channelStateChangerLock = new ReentrantLock();
46 | }
47 |
48 | @Override
49 | public void stopChannel(Integer channelId) {
50 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.STOPPED));
51 | }
52 |
53 | @Override
54 | public void reopenChannel(Integer channelId) {
55 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.OPEN));
56 | }
57 |
58 | @Override
59 | public void terminateChannel(Integer channelId) {
60 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.TERMINATED));
61 | }
62 |
63 | @Override
64 | public Channel>,
65 | ConcurrentHashMap>> getChannel(Integer channelId)
66 | throws NoSuchChannelException, NullObjectException {
67 | if(channelId == null){
68 | throw new NullObjectException("channelId is null");
69 | }
70 | if(!channelMap.containsKey(channelId)){
71 | throw new NoSuchChannelException("Channel with id " + channelId + " does not exists");
72 | }
73 | if(channelMap.get(channelId) == null){
74 | throw new NoSuchChannelException("Channel with id " + channelId + " does not exists");
75 | }
76 | return channelMap.get(channelId);
77 | }
78 |
79 | @Override
80 | public void addSubscriber(Integer channelId, T subscriber, Integer subscriberId)
81 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
82 | runSubscriptionTask(channelId, subscriber, subscriberId);
83 | }
84 |
85 | @Override
86 | public void addSubscriber(T subscriber)
87 | throws AlreadyExistsException, NullObjectException{
88 | try {
89 | runSubscriptionTask(Channel.DEFAULT_CHANNEL_ID, subscriber, subscriber.hashCode());
90 | }catch (NoSuchChannelException | IllegalChannelStateException | PermissionException e){
91 | e.printStackTrace();
92 | }
93 | }
94 |
95 | @Override
96 | public void addSubscriber(Integer channelId, T subscriber)
97 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
98 | runSubscriptionTask(channelId, subscriber, subscriber.hashCode());
99 | }
100 |
101 | @Override
102 | public void addSubscriber(V owner, Integer channelId, T subscriber)
103 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
104 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriber.hashCode());
105 | }
106 |
107 | @Override
108 | public void addSubscriber(V owner, Integer channelId, T subscriber, Integer subscriberId)
109 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
110 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriberId);
111 | }
112 |
113 | @Override
114 | public void addSubscriberAsync(V owner, Integer channelId, T subscriber) {
115 | executorService.execute(new SubscribePrivateTaskRunner<>(owner, channelId, subscriber, subscriber.hashCode()));
116 | }
117 |
118 | @Override
119 | public void addSubscriberAsync(V owner, Integer channelId, T subscriber, Integer subscriberId) {
120 | executorService.execute(new SubscribePrivateTaskRunner<>(owner, channelId, subscriber, subscriberId));
121 | }
122 |
123 | @Override
124 | public void addSubscriberAsync(Integer channelId, T subscriber, Integer subscriberId) {
125 | executorService.execute(new SubscribeTaskRunner<>(channelId, subscriber, subscriberId));
126 | }
127 |
128 | @Override
129 | public void addSubscriberAsync(T subscriber) {
130 | executorService.execute(new SubscribeTaskRunner<>(Channel.DEFAULT_CHANNEL_ID, subscriber, subscriber.hashCode()));
131 | }
132 |
133 | @Override
134 | public void addSubscriberAsync(Integer channelId, T subscriber) {
135 | executorService.execute(new SubscribeTaskRunner<>(channelId, subscriber, subscriber.hashCode()));
136 | }
137 |
138 | @Override
139 | public void removeSubscriber(T subscriber)
140 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException{
141 |
142 | Channel channel = getChannel(Channel.DEFAULT_CHANNEL_ID);
143 | channel.removeSubscriber(subscriber);
144 | }
145 |
146 | @Override
147 | public void removeSubscriber(Integer channelId, T subscriber)
148 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException{
149 |
150 | Channel channel = getChannel(channelId);
151 | channel.removeSubscriber(subscriber);
152 | }
153 |
154 | @Override
155 | public void removeSubscriber(T registeredSubscriber, Integer channelId, Integer subscriberId)
156 | throws InvalidSubscriberException, NoSuchChannelException, PermissionException, NullObjectException{
157 |
158 | Channel channel = getChannel(channelId);
159 | if(channel instanceof PrivateChannel){
160 | PrivateChannel privateChannel = (PrivateChannel)channel;
161 | boolean isPermissionGranted = false;
162 | for(Object weakReferenceObj : privateChannel.getSubscriberMap().values()){
163 | if(weakReferenceObj instanceof WeakReference) {
164 | Object subscriber = ((WeakReference)weakReferenceObj).get();
165 | if (subscriber != null && subscriber == registeredSubscriber) {
166 | isPermissionGranted = true;
167 | break;
168 | }
169 | }
170 | }
171 | if(isPermissionGranted) {
172 | privateChannel.removeSubscriber(subscriberId);
173 | }else{
174 | throw new PermissionException("Only the subscriber of the private channel is allowed to broadcast on private channel");
175 | }
176 | }else{
177 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists");
178 | }
179 | }
180 |
181 | @Override
182 | public Collection extends WeakReference>> getAllSubscribersWeakRef(Integer channelId) throws NoSuchChannelException {
183 | try {
184 | Channel>,
185 | ConcurrentHashMap>> channel = getChannel(channelId);
186 | return channel.getAllSubscribersReferenceList();
187 | }catch (NullObjectException e){
188 | e.printStackTrace();
189 | }
190 | return null;
191 | }
192 |
193 | @Override
194 | public void broadcast(T msg){
195 | try {
196 | runBroadcastTask(Channel.DEFAULT_CHANNEL_ID, msg);
197 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){
198 | e.printStackTrace();
199 | }
200 | }
201 |
202 | @Override
203 | public void broadcastAsync(T msg) throws JPostNotRunningException{
204 | if(executorService.isShutdown()){
205 | throw new JPostNotRunningException("JPost is shutdown");
206 | }
207 | executorService.execute(new MsgTasKRunner<>(Channel.DEFAULT_CHANNEL_ID, msg));
208 | }
209 |
210 | @Override
211 | public void broadcast(Integer channelId, T msg, Integer... subscribers){
212 | try {
213 | runBroadcastTask(channelId, msg, subscribers);
214 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){
215 | e.printStackTrace();
216 | }
217 | }
218 |
219 | @Override
220 | public void broadcastAsync(Integer channelId, T msg, Integer... subscribers) throws JPostNotRunningException{
221 | if(executorService.isShutdown()){
222 | throw new JPostNotRunningException("JPost is shutdown");
223 | }
224 | executorService.execute(new MsgTasKRunner(channelId, msg, subscribers));
225 | }
226 |
227 | @Override
228 | public void broadcast(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers){
229 | try {
230 | runPrivateBroadcastTask(registeredSubscriber, channelId, msg, subscribers);
231 | }catch (NoSuchChannelException | IllegalChannelStateException | PermissionException| NullObjectException e){
232 | e.printStackTrace();
233 | }
234 | }
235 |
236 | @Override
237 | public void broadcastAsync(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers) throws JPostNotRunningException{
238 | if(executorService.isShutdown()){
239 | throw new JPostNotRunningException("JPost is shutdown");
240 | }
241 | executorService.execute(new PrivateMsgTasKRunner<>(registeredSubscriber, channelId, msg, subscribers));
242 | }
243 |
244 | private class ChannelStateTasKRunner implements Runnable{
245 |
246 | private Integer channelId;
247 | private ChannelState state;
248 |
249 | ChannelStateTasKRunner(Integer channelId, ChannelState state) {
250 | this.channelId = channelId;
251 | this.state = state;
252 | new Thread(this, String.valueOf(channelId));
253 | }
254 |
255 | @Override
256 | public void run(){
257 | try {
258 | channelStateChangerLock.lock();
259 | Channel channel = getChannel(channelId);
260 | if (channel.getChannelState() == ChannelState.TERMINATED) {
261 | throw new IllegalChannelStateException("Channel with id " + channelId + " has been terminated");
262 | }
263 | if(channel instanceof CustomChannel){
264 | switch (state){
265 | case OPEN:
266 | ((CustomChannel)channel).startChannel();
267 | break;
268 | case STOPPED:
269 | ((CustomChannel)channel).stopChannel();
270 | break;
271 | case TERMINATED:
272 | ((CustomChannel)channel).terminateChannel();
273 | channelMap.remove(channelId);
274 | break;
275 | }
276 | }
277 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException e){
278 | e.printStackTrace();
279 | }finally {
280 | channelStateChangerLock.unlock();
281 | }
282 | }
283 | }
284 |
285 | private class MsgTasKRunner implements Runnable{
286 |
287 | private Integer channelId;
288 | private T msg;
289 | private Integer[] subscribers;
290 |
291 | MsgTasKRunner(Integer channelId, T msg, Integer... subscribers) {
292 | this.channelId = channelId;
293 | this.msg = msg;
294 | this.subscribers = subscribers;
295 | new Thread(this, String.valueOf(channelId));
296 | }
297 |
298 | @Override
299 | public void run(){
300 | try{
301 | runBroadcastTask(channelId, msg, subscribers);
302 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){
303 | e.printStackTrace();
304 | }
305 | }
306 | }
307 |
308 | private class PrivateMsgTasKRunner implements Runnable{
309 |
310 | private Integer channelId;
311 | private T msg;
312 | private V registeredSubscriber;
313 | private Integer[] subscribers;
314 |
315 | PrivateMsgTasKRunner(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers) {
316 | this.registeredSubscriber = registeredSubscriber;
317 | this.channelId = channelId;
318 | this.msg = msg;
319 | this.subscribers = subscribers;
320 | new Thread(this, String.valueOf(channelId));
321 | }
322 |
323 | @Override
324 | public void run(){
325 | try{
326 | runPrivateBroadcastTask(registeredSubscriber, channelId, msg, subscribers);
327 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){
328 | e.printStackTrace();
329 | }
330 | }
331 | }
332 |
333 | private class SubscribeTaskRunner implements Runnable{
334 |
335 | private Integer channelId;
336 | private Integer subscriberId;
337 | private T subscriber;
338 |
339 | SubscribeTaskRunner(Integer channelId, T subscriber, Integer subscriberId) {
340 | this.channelId = channelId;
341 | this.subscriberId = subscriberId;
342 | this.subscriber = subscriber;
343 | new Thread(this, String.valueOf(channelId));
344 | }
345 |
346 | @Override
347 | public void run(){
348 | try {
349 | runSubscriptionTask(channelId, subscriber, subscriberId);
350 | }catch (NoSuchChannelException | NullObjectException | AlreadyExistsException
351 | | IllegalChannelStateException| PermissionException e){
352 | e.printStackTrace();
353 | }
354 | }
355 | }
356 |
357 | private class SubscribePrivateTaskRunner implements Runnable{
358 |
359 | private Integer channelId;
360 | private Integer subscriberId;
361 | private V owner;
362 | private T subscriber;
363 |
364 | SubscribePrivateTaskRunner(V owner, Integer channelId, T subscriber, Integer subscriberId) {
365 | this.owner = owner;
366 | this.channelId = channelId;
367 | this.subscriberId = subscriberId;
368 | this.subscriber = subscriber;
369 | new Thread(this, String.valueOf(channelId));
370 | }
371 |
372 | @Override
373 | public void run(){
374 | try {
375 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriberId);
376 | }catch (NoSuchChannelException | NullObjectException | AlreadyExistsException
377 | | IllegalChannelStateException |PermissionException e){
378 | e.printStackTrace();
379 | }
380 | }
381 | }
382 |
383 | private void runBroadcastTask(Integer channelId, T msg, Integer... subscribers)
384 | throws NoSuchChannelException, IllegalChannelStateException, NullObjectException, PermissionException{
385 |
386 | Channel channel = getChannel(channelId);
387 | if(channel.getChannelState() == ChannelState.OPEN){
388 | if(channel instanceof PrivateChannel){
389 | throw new PermissionException("Only subscribers of private channel can send/receive messages over it");
390 | }
391 | if(channel instanceof PublicChannel && subscribers.length > 0){
392 | ((PublicChannel)channel).broadcast(msg, subscribers);
393 | }else {
394 | channel.broadcast(msg);
395 | }
396 | }else{
397 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState());
398 | }
399 | }
400 |
401 | private void runPrivateBroadcastTask(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)
402 | throws NoSuchChannelException, PermissionException, IllegalChannelStateException, NullObjectException{
403 |
404 | Channel channel = getChannel(channelId);
405 | if(channel.getChannelState() == ChannelState.OPEN){
406 | if(channel instanceof PrivateChannel){
407 | PrivateChannel privateChannel = (PrivateChannel)channel;
408 | boolean isPermissionGranted = false;
409 | for(Object weakReferenceObj : privateChannel.getSubscriberMap().values()){
410 | if(weakReferenceObj instanceof WeakReference) {
411 | Object subscriber = ((WeakReference)weakReferenceObj).get();
412 | if (subscriber != null && subscriber == registeredSubscriber) {
413 | isPermissionGranted = true;
414 | break;
415 | }
416 | }
417 | }
418 | if(isPermissionGranted) {
419 | if(subscribers.length > 0) {
420 | privateChannel.broadcast(msg, subscribers);
421 | }else{
422 | privateChannel.broadcast(msg);
423 | }
424 | }else{
425 | throw new PermissionException("Only the subscriber of the private channel is allowed to broadcast on private channel");
426 | }
427 | }else{
428 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists");
429 | }
430 | }else{
431 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name());
432 | }
433 | }
434 |
435 | private void runSubscriptionTask(Integer channelId, T subscriber, Integer subscriberId)
436 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
437 |
438 | Channel channel = getChannel(channelId);
439 | if(channel instanceof PrivateChannel){
440 | throw new PermissionException("Only owner of the private channel can add a subscriber to private channel");
441 | }
442 | if(channel.getChannelState() == ChannelState.OPEN){
443 | channel.addSubscriber(subscriber, subscriberId);;
444 | }else{
445 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name());
446 | }
447 | }
448 |
449 | protected void runPrivateSubscriptionTask(V owner, Integer channelId, T subscriber, Integer subscriberId)
450 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{
451 |
452 | Channel channel = getChannel(channelId);
453 | if(channel.getChannelState() == ChannelState.OPEN){
454 | if(channel instanceof PrivateChannel){
455 | PrivateChannel privateChannel = (PrivateChannel)channel;
456 | if(privateChannel.getChannelOwnerRef() != null){
457 | Object channelOwner = privateChannel.getChannelOwnerRef().get();
458 | if(channelOwner != null && channelOwner.equals(owner)) {
459 | privateChannel.addSubscriber(subscriber, subscriberId);
460 | }else{
461 | throw new PermissionException("Only the owner of the private channel is allowed to add subscribers to private channel");
462 | }
463 | }
464 | }else{
465 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists");
466 | }
467 | }else{
468 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name());
469 | }
470 | }
471 |
472 | protected ConcurrentHashMap>,
473 | ConcurrentHashMap>>> getChannelMap() {
474 | return channelMap;
475 | }
476 |
477 | public ExecutorService getExecutorService() {
478 | return executorService;
479 | }
480 |
481 | public void setExecutorService(ExecutorService executorService) {
482 | this.executorService = executorService;
483 | }
484 | }
485 |
--------------------------------------------------------------------------------